@go-to-k/cdkd 0.283.35 → 0.284.0

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.
@@ -9887,20 +9887,32 @@ const SECRET_MASK = "***";
9887
9887
  * homing it here means no call site has to thread it: the four sibling writers
9888
9888
  * #1910 fixes pass a position SOURCE and nothing else.
9889
9889
  *
9890
- * Its lifetime matches the resolver's `cachedDynamicReferences` — the resolver
9891
- * clears both together, and that shared lifetime is the point: this set IS the
9892
- * resolver's own SecureString verdict store, which already had exactly this
9893
- * scope, so nothing is widened by homing it here.
9894
- *
9895
- * Process-wide is therefore INHERITED, not claimed to be ideal. It is not
9896
- * strictly sound across regions or accounts in one run — the same expression
9897
- * can name a `SecureString` in one region and a plain `String` in another but
9898
- * `cachedDynamicReferences` caches the resolved VALUE under the same
9899
- * assumption, so a per-region store here would fix nothing on its own. Note
9900
- * which way the imprecision points: an entry only ever GRANTS "persist the
9901
- * source leaf verbatim", and the leaf is the resource's own template
9902
- * expression, so the failure mode is a public reference stored as an expression
9903
- * (a spurious UPDATE, issue #1901's class), never a secret stored as plaintext.
9890
+ * Its lifetime NO LONGER matches the resolver's `cachedDynamicReferences`, and
9891
+ * that divergence is now deliberate (issue
9892
+ * [#1933](https://github.com/go-to-k/cdkd/issues/1933)). The resolved VALUES
9893
+ * moved onto the RESOLVER INSTANCE one per stack, each carrying its own
9894
+ * region — because a value is only true for the region that read it. A VERDICT
9895
+ * is a statement about a reference's TYPE and has to be readable with no
9896
+ * resolver in hand: {@link isKnownSecretExpression} is consulted from the
9897
+ * redaction path, whose callers thread a position SOURCE and nothing else. So
9898
+ * this set stays process-wide while the values do not, and
9899
+ * `resetAccountInfoCache` now clears only this one.
9900
+ *
9901
+ * Process-wide is therefore CHOSEN here rather than inherited, and the choice
9902
+ * is what makes a stale verdict correctable: a resolver whose fresh
9903
+ * `GetParameter` reports a public `Type` RETRACTS the entry
9904
+ * ({@link forgetSecretExpression}) for every later reader, which a per-region
9905
+ * store would scope away. It is still not strictly sound across regions or
9906
+ * accounts in one run — the same expression can name a `SecureString` in one
9907
+ * region and a plain `String` in another — but note which way the imprecision
9908
+ * points in EACH direction now that the two stores can disagree. An entry only
9909
+ * ever GRANTS "persist the source leaf verbatim", so a verdict inherited from
9910
+ * another region can at worst store a public reference as an expression (a
9911
+ * spurious UPDATE, issue #1901's class), never a secret as plaintext. And the
9912
+ * opposite move — another region RETRACTING a verdict this stack still needs —
9913
+ * cannot un-redact anything either, because each of the resolver's own cache
9914
+ * entries carries the verdict that produced it and re-records on a hit without
9915
+ * consulting this set.
9904
9916
  */
9905
9917
  const recordedSecretExpressions$1 = /* @__PURE__ */ new Set();
9906
9918
  /** Remember that `expression` resolves to a secret. Called by the resolver. */
@@ -12152,15 +12164,19 @@ let cachedAccountIdentity = null;
12152
12164
  */
12153
12165
  const cachedAvailabilityZones = {};
12154
12166
  /**
12155
- * Cache for resolved dynamic references (secretsmanager, ssm)
12156
- */
12157
- const cachedDynamicReferences = {};
12158
- /**
12159
12167
  * The `{{resolve:...}}` expressions this process has PROVEN resolve to a
12160
12168
  * SECRET, reached through `secret-redaction.ts`'s `recordedSecretExpressions`
12161
- * store. Lifetime is {@link cachedDynamicReferences}'s `resetAccountInfoCache`
12162
- * clears both, so a stale verdict can never decide secret-ness for a reference
12163
- * whose resolved value that call just asked to forget.
12169
+ * store. Process-global, and cleared by `resetAccountInfoCache` so a test (or a
12170
+ * later phase) cannot inherit a verdict it just asked to forget.
12171
+ *
12172
+ * NOTE this store is deliberately WIDER-lived than the resolved VALUES it was
12173
+ * once paired with: those moved onto the resolver instance (issue #1933), while
12174
+ * a verdict is a statement about a reference's TYPE, which the redaction path
12175
+ * must be able to read with no resolver in hand. The asymmetry is safe in the
12176
+ * one direction that matters — a verdict inherited across regions can only make
12177
+ * a reference be treated AS a secret (persisted as its expression, never as
12178
+ * plaintext), and the reverse case re-asks AWS because the fresh response is
12179
+ * authoritative and the value cache no longer answers for another region.
12164
12180
  *
12165
12181
  * `ssm` is the kind that NEEDS the memory (issue #1901). A plain `ssm`
12166
12182
  * reference is not a secret by SPELLING the way `secretsmanager` is — whether
@@ -12249,6 +12265,24 @@ function accountInfoFor(identity, overrideRegion) {
12249
12265
  * the same deploy heal.
12250
12266
  */
12251
12267
  const FABRICATED_ACCOUNT_INFO_TTL_MS = 1e4;
12268
+ /**
12269
+ * Retries after the first attempt for a dynamic-reference lookup, THROTTLE-shaped
12270
+ * failures only (issue #1933 review). Everything else — a missing parameter, a
12271
+ * denied secret — is a real answer and is thrown to the caller unchanged.
12272
+ *
12273
+ * It matters more since the cache became per-resolver AND stopped memoizing a
12274
+ * value whose ssm `Type` was unclassifiable: both raise the call COUNT for the
12275
+ * same template (one lookup per resolver rather than per process; one per
12276
+ * occurrence for the anomalous type), and a bare `send` turned the resulting
12277
+ * throttle into an aborted deploy. At the default backoff (1s -> 2s -> 4s -> 8s)
12278
+ * this adds at most ~15s of sleep, against re-running the whole deploy.
12279
+ */
12280
+ const MAX_DYNAMIC_REFERENCE_THROTTLE_RETRIES = 4;
12281
+ /**
12282
+ * Test seam: overriding `sleep` lets unit tests drive the backoff schedule
12283
+ * without real waits (mirrors `describeTypeRetryDelays`).
12284
+ */
12285
+ const dynamicReferenceRetryDelays = {};
12252
12286
  /** Test seam for {@link FABRICATED_ACCOUNT_INFO_TTL_MS} expiry. */
12253
12287
  const accountInfoClock = { now: () => Date.now() };
12254
12288
  let fabricatedAccountIdentity = null;
@@ -12435,6 +12469,89 @@ var IntrinsicFunctionResolver = class {
12435
12469
  * deploy summary.
12436
12470
  */
12437
12471
  physicalIdFallbackCount = 0;
12472
+ /**
12473
+ * Resolved `{{resolve:secretsmanager:...}}` / `{{resolve:ssm:...}}` values,
12474
+ * keyed by the full expression — INSTANCE-scoped, which closes the CACHE half
12475
+ * of issue [#1933](https://github.com/go-to-k/cdkd/issues/1933). The issue is
12476
+ * only PARTIALLY addressed by this field: see "what this does NOT settle"
12477
+ * below.
12478
+ *
12479
+ * It used to be a module-global map keyed by the expression ALONE, and both
12480
+ * halves of that were wrong for the same reason: the key and the lifetime
12481
+ * were narrower than the value they stood for.
12482
+ *
12483
+ * - REGION. Secrets Manager secrets and SSM parameters are regional and
12484
+ * independent — the same NAME in `us-east-1` and `ap-northeast-1` is two
12485
+ * different values, routinely two different credentials — so the first
12486
+ * region to resolve an expression won it for the whole process, and every
12487
+ * later stack in every other region silently reused that value.
12488
+ * - STACK. Nothing reset the map between stacks, so a second stack's
12489
+ * resolution cache-HIT and skipped the lookup that re-records the value as
12490
+ * a secret. `cdkd scrub --all` then found an empty secrets map for that
12491
+ * stack and reported it clean.
12492
+ *
12493
+ * Instance scope settles both at once because a region boundary and a stack
12494
+ * boundary are BOTH resolver boundaries in cdkd: {@link resolverRegion} is
12495
+ * fixed at construction, and every caller builds one resolver per stack
12496
+ * (`DeployEngine` per deploy, `scrub` / `import` / `diff-recursive` /
12497
+ * `rollback-executor` per stack). Re-keying by region alone would have left
12498
+ * the stack half open, which is why the lifetime — not the key — is what
12499
+ * moved.
12500
+ *
12501
+ * ONE caller is a known EXCEPTION to that invariant, and it is written down
12502
+ * here because an invariant recorded without its exception is how the next
12503
+ * change breaks it: `cdkd export` builds a single `paramResolver`
12504
+ * (`src/cli/commands/export.ts`, the `buildResolvedParametersPerStack`
12505
+ * pre-pass) and shares it across every node of a nested-stack tree, while the
12506
+ * nodes carry a per-node `region`. It is safe TODAY for two independent
12507
+ * reasons — the resolver is constructed with the tree's single `rootRegion`
12508
+ * and nested children do not yet diverge from it, and that pre-pass passes no
12509
+ * `recordedSecretValues` bag, so neither the region nor the secrets-recording
12510
+ * dimension has anything to cross. Both stop holding the moment cross-region
12511
+ * nested stacks ship or that pass starts recording secrets; a resolver per
12512
+ * node is the fix then, not a wider key here.
12513
+ *
12514
+ * What this does NOT settle — issue
12515
+ * [#1957](https://github.com/go-to-k/cdkd/issues/1957) owns it: the lookups
12516
+ * themselves still go through the process-ambient `getAwsClients()` singleton
12517
+ * (see `resolveSecretsManagerReference` / `resolveSSMReference`), whose region
12518
+ * is whichever the process installed last. So a resolver constructed for
12519
+ * region B while the ambient clients point at region A still reads A on its
12520
+ * FIRST resolution — no cache involved, so nothing here can prevent it.
12521
+ * `cdkd deploy` re-pins the singleton per stack, which makes a SERIAL
12522
+ * multi-region deploy correct end to end, but the default
12523
+ * `--stack-concurrency 4` races for it (a hazard `deploy.ts` already
12524
+ * documents) and `cdkd scrub` installs its clients once while resolving
12525
+ * stacks in several regions. The split of ownership is therefore: THIS field
12526
+ * closes the cache as a cross-region / cross-stack carrier, while #1957 owns
12527
+ * the wrong-region READ — which is the outcome #1933's title names, so #1933
12528
+ * is not fully resolved until #1957 lands. Pinning the lookup to
12529
+ * {@link resolverRegion} means constructing region-scoped clients, which is a
12530
+ * credentials decision (a bare `new SSMClient({ region })` drops the ambient
12531
+ * profile / assume-role config) and belongs to #1957 rather than here.
12532
+ */
12533
+ cachedDynamicReferences = /* @__PURE__ */ new Map();
12534
+ /**
12535
+ * `<parameter name>\u0000<reported Type>` pairs this resolver has already
12536
+ * warned about (issue #1933 review).
12537
+ *
12538
+ * Keyed on the PAIR rather than the name alone: two different anomalous types
12539
+ * for one parameter are two different facts — the line REPORTS the type, so
12540
+ * suppressing the second would hide a `Type` nobody has seen yet behind one
12541
+ * that was already explained. The volume problem this set exists for is N
12542
+ * IDENTICAL lines for N occurrences of one reference, which the pair still
12543
+ * bounds, because the type is a property of the parameter rather than of the
12544
+ * occurrence.
12545
+ *
12546
+ * The warning is per LOOKUP, and a parameter with an anomalous `Type` is
12547
+ * deliberately never cached (see `cacheable` in `resolveDynamicReferences`),
12548
+ * so it is re-looked-up for every occurrence of the reference in the stack —
12549
+ * which without this set means one identical warn line per occurrence per
12550
+ * pass, on the exact template that most needs the line to be READ. Scoped to
12551
+ * the resolver, like the value cache: a different stack genuinely deserves
12552
+ * its own warning, since the parameter it names may be a different region's.
12553
+ */
12554
+ warnedUnrecognizedSsmTypes = /* @__PURE__ */ new Set();
12438
12555
  constructor(region, options) {
12439
12556
  this.resolverRegion = region || process.env["AWS_REGION"] || "us-east-1";
12440
12557
  this.strictGetAtt = options?.strictGetAtt ?? false;
@@ -14014,21 +14131,35 @@ var IntrinsicFunctionResolver = class {
14014
14131
  const service = inner.split(":")[0];
14015
14132
  const isKnownSecret = service === "secretsmanager" || recordedSecretExpressions.has(fullMatch);
14016
14133
  if (isKnownSecret && context?.skipDynamicReferences) continue;
14017
- if (fullMatch in cachedDynamicReferences) {
14018
- const cached = cachedDynamicReferences[fullMatch];
14019
- if (isKnownSecret && cached) context?.recordedSecretValues?.set(cached, fullMatch);
14020
- result = result.replace(fullMatch, () => cached);
14134
+ const cached = this.cachedDynamicReferences.get(fullMatch);
14135
+ if (cached) {
14136
+ if (cached.secret && cached.value) context?.recordedSecretValues?.set(cached.value, fullMatch);
14137
+ result = result.replace(fullMatch, () => cached.value);
14021
14138
  continue;
14022
14139
  }
14023
14140
  const parts = inner.split(":");
14024
14141
  let resolved;
14025
14142
  let isSecret = isKnownSecret;
14143
+ /**
14144
+ * May the resolved value be REMEMBERED, or must the next pass re-ask?
14145
+ *
14146
+ * Cleared for exactly the answers the verdict store refuses to pin — an
14147
+ * ssm parameter judged secret from a `Type` that is not a definitive
14148
+ * `SecureString` (issue #1901's fail-closed arm). Caching one would pin
14149
+ * the transient answer for the whole resolver anyway, which is what the
14150
+ * refusal to memoize exists to prevent: before the value cache became
14151
+ * instance-scoped this was already true process-wide, and the
14152
+ * "next pass re-asks" property only ever held on the comparison path,
14153
+ * which caches nothing (issue #1933).
14154
+ */
14155
+ let cacheable = true;
14026
14156
  if (service === "secretsmanager") resolved = await this.resolveSecretsManagerReference(inner);
14027
14157
  else if (service === "ssm") {
14028
14158
  const decrypt = context?.skipDynamicReferences !== true;
14029
14159
  const param = await this.resolveSSMReference(parts, decrypt);
14030
14160
  if (param.type === "SecureString") recordedSecretExpressions.add(fullMatch);
14031
14161
  else if (!param.secure) recordedSecretExpressions.delete(fullMatch);
14162
+ else cacheable = false;
14032
14163
  isSecret = param.secure;
14033
14164
  if (param.secure) {
14034
14165
  if (!decrypt) continue;
@@ -14038,7 +14169,10 @@ var IntrinsicFunctionResolver = class {
14038
14169
  this.logger.warn(`Unsupported dynamic reference service: ${service}`);
14039
14170
  continue;
14040
14171
  }
14041
- cachedDynamicReferences[fullMatch] = resolved;
14172
+ if (cacheable) this.cachedDynamicReferences.set(fullMatch, {
14173
+ value: resolved,
14174
+ secret: isSecret
14175
+ });
14042
14176
  if (isSecret && resolved) {
14043
14177
  context?.recordedSecretValues?.set(resolved, fullMatch);
14044
14178
  if (service === "secretsmanager") recordedSecretExpressions.add(fullMatch);
@@ -14098,7 +14232,7 @@ var IntrinsicFunctionResolver = class {
14098
14232
  ...versionStage && versionStage !== "" && { VersionStage: versionStage },
14099
14233
  ...versionId && versionId !== "" && { VersionId: versionId }
14100
14234
  });
14101
- const secretString = (await client.send(command)).SecretString;
14235
+ const secretString = (await this.sendWithThrottleRetry(() => client.send(command), `secretsmanager:${secretId}`)).SecretString;
14102
14236
  if (!secretString) throw new Error(`Dynamic reference: secret '${secretId}' does not contain a SecretString value`);
14103
14237
  if (jsonKey) try {
14104
14238
  const keyValue = JSON.parse(secretString)[jsonKey];
@@ -14197,6 +14331,43 @@ var IntrinsicFunctionResolver = class {
14197
14331
  return parts.join(":");
14198
14332
  }
14199
14333
  /**
14334
+ * Run one dynamic-reference lookup, retrying THROTTLE-shaped failures only
14335
+ * (issue #1933 review).
14336
+ *
14337
+ * Both lookups behind `{{resolve:...}}` were bare `send` calls, so a single
14338
+ * `Rate exceeded` aborted the deploy. That was already the wrong trade for a
14339
+ * read, and this PR raises the call count on both paths: the resolved-value
14340
+ * cache is per-resolver now (one lookup per stack rather than one per
14341
+ * process), and a value whose ssm `Type` came back unclassifiable is
14342
+ * deliberately not cached at all (one lookup per OCCURRENCE, so it re-asks
14343
+ * AWS rather than inheriting a transient verdict). Retrying only the throttle
14344
+ * shape keeps every real answer — `ParameterNotFound`, `AccessDenied`, a
14345
+ * malformed reference — failing fast and unchanged.
14346
+ *
14347
+ * Two bounds, both NAMED rather than fixed here:
14348
+ *
14349
+ * - No `isInterrupted` is threaded, so a Ctrl-C landing inside the backoff is
14350
+ * only noticed when that sleep ends — worst case ~8s, ~15s across the whole
14351
+ * schedule. `withRetry` supports the hook, but the only interrupt state in
14352
+ * the tree is `DeployEngine.interrupted`, which reaches nothing here;
14353
+ * wiring it means a resolver option threaded from that engine.
14354
+ * - It says NOTHING about concurrency. The client is captured before the
14355
+ * first attempt, so a sibling stack's teardown (`stackAwsClients.destroy()`
14356
+ * in `deploy.ts`) during a backoff surfaces as a raw, non-throttle-shaped
14357
+ * failure on the next attempt. That is a property of the ambient-singleton
14358
+ * design this PR deliberately does not touch (issue
14359
+ * [#1957](https://github.com/go-to-k/cdkd/issues/1957)), not something the
14360
+ * retry makes safe.
14361
+ */
14362
+ sendWithThrottleRetry(operation, label) {
14363
+ return withRetry(operation, label, {
14364
+ maxRetries: MAX_DYNAMIC_REFERENCE_THROTTLE_RETRIES,
14365
+ isRetryable: (_message, error) => isThrottlingError(error),
14366
+ logger: this.logger,
14367
+ ...dynamicReferenceRetryDelays.sleep ? { sleep: dynamicReferenceRetryDelays.sleep } : {}
14368
+ });
14369
+ }
14370
+ /**
14200
14371
  * Resolve an `{{resolve:ssm:...}}` dynamic reference, reporting whether the
14201
14372
  * parameter is a `SecureString` (issue #1901).
14202
14373
  *
@@ -14220,12 +14391,13 @@ var IntrinsicFunctionResolver = class {
14220
14391
  Name: parameterName,
14221
14392
  WithDecryption: decrypt
14222
14393
  });
14223
- const response = await client.send(command);
14394
+ const response = await this.sendWithThrottleRetry(() => client.send(command), `ssm:${parameterName}`);
14224
14395
  const paramValue = response.Parameter?.Value;
14225
14396
  if (paramValue === void 0 || paramValue === null) throw new Error(`Dynamic reference: SSM parameter '${parameterName}' not found or has no value`);
14226
14397
  const paramType = response.Parameter?.Type;
14227
14398
  const secure = paramType !== "String" && paramType !== "StringList";
14228
- if (secure && paramType !== "SecureString") {
14399
+ if (secure && paramType !== "SecureString" && !this.warnedUnrecognizedSsmTypes.has(`${parameterName}\u0000${String(paramType)}`)) {
14400
+ this.warnedUnrecognizedSsmTypes.add(`${parameterName}\u0000${String(paramType)}`);
14229
14401
  const reported = paramType === void 0 ? "(absent)" : `'${String(paramType)}'`;
14230
14402
  this.logger.warn(`SSM parameter '${parameterName}' reported an unrecognized Type ${reported} — treating its value as a secret, so cdkd will persist the {{resolve:ssm:...}} expression rather than the resolved value. Declare the parameter as String / StringList if it is public config.`);
14231
14403
  }
@@ -15097,7 +15269,7 @@ var CloudControlProvider = class {
15097
15269
  if (context?.finalSnapshotIdentifier !== void 0) throw new ProvisioningError(`${logicalId} (${resourceType}) requires a final snapshot (DeletionPolicy: Snapshot), but the Cloud Control API delete route has no final-snapshot parameter. Re-run with --skip-final-snapshot after snapshotting manually, or retain the resource.`, resourceType, logicalId, physicalId);
15098
15270
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
15099
15271
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
15100
- const { ASGProvider } = await import("./asg-provider-xC0UiCjt.js").then((n) => n.n);
15272
+ const { ASGProvider } = await import("./asg-provider-CMvwsTc7.js").then((n) => n.n);
15101
15273
  return await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
15102
15274
  }
15103
15275
  const isProtectedEc2Instance = context?.removeProtection === true && resourceType === "AWS::EC2::Instance";
@@ -19667,18 +19839,27 @@ var IAMRoleProvider = class {
19667
19839
  const reason = newRoleName !== physicalId ? "RoleName" : "Path";
19668
19840
  this.logger.debug(`${reason} changed, replacing role: ${physicalId} (${reason}: ${reason === "RoleName" ? `${physicalId} -> ${newRoleName}` : `${oldPath} -> ${newPath}`})`);
19669
19841
  const createResult = await this.create(logicalId, resourceType, properties);
19842
+ let orphanReason;
19670
19843
  try {
19671
19844
  const deleteResult = await this.delete(logicalId, physicalId, resourceType);
19672
- if (deleteResult?.outcome === "skipped") this.logger.warn(`Skipped deleting old role ${physicalId} during replacement: ${deleteResult.reason}. The old role may be orphaned and require manual cleanup.`);
19845
+ if (deleteResult?.outcome === "skipped") {
19846
+ orphanReason = `old role ${physicalId} was not deleted: ${deleteResult.reason}`;
19847
+ this.logger.warn(`Skipped deleting old role ${physicalId} during replacement: ${deleteResult.reason}. The old role may be orphaned and require manual cleanup.`);
19848
+ }
19673
19849
  } catch (error) {
19850
+ orphanReason = `old role ${physicalId} could not be deleted: ${String(error)}`;
19674
19851
  this.logger.warn(`Failed to delete old role ${physicalId} during replacement: ${String(error)}. The old role may be orphaned and require manual cleanup.`);
19675
19852
  }
19676
- const result = {
19853
+ const base = {
19677
19854
  physicalId: createResult.physicalId,
19678
- wasReplaced: true
19855
+ wasReplaced: true,
19856
+ ...createResult.attributes ? { attributes: createResult.attributes } : {}
19679
19857
  };
19680
- if (createResult.attributes) result.attributes = createResult.attributes;
19681
- return result;
19858
+ return orphanReason !== void 0 ? {
19859
+ ...base,
19860
+ outcome: "partial",
19861
+ reason: orphanReason
19862
+ } : base;
19682
19863
  }
19683
19864
  try {
19684
19865
  const updateParams = { RoleName: physicalId };
@@ -21603,6 +21784,62 @@ function deleteSkippedMessage(logicalId, physicalId, reason, duringClause) {
21603
21784
  return `cdkd could not address ${logicalId} (${physicalId}) ${duringClause}, so it was NOT deleted and may still exist: ${reason}`;
21604
21785
  }
21605
21786
 
21787
+ //#endregion
21788
+ //#region src/deployment/update-outcome.ts
21789
+ /**
21790
+ * Consumption of {@link ResourceUpdateResult}'s `'partial'` arm (issue
21791
+ * [#1819](https://github.com/go-to-k/cdkd/issues/1819)) — the twin of
21792
+ * {@link ./delete-outcome.ts} for the UPDATE verb.
21793
+ *
21794
+ * `ResourceProvider.update` gained an outcome channel whose `'partial'` arm
21795
+ * means **the resource was updated, and something the update was responsible
21796
+ * for retiring survives and is no longer tracked by cdkd**. The four providers
21797
+ * that implement a REPLACEMENT inside `update()` by pairing create and delete
21798
+ * are the producers; before the channel existed they emitted a `logger.warn`
21799
+ * and the deploy exited 0 with the old resource alive and out of state.
21800
+ *
21801
+ * **The module must stay a LEAF — no imports beyond the type, ever.** Same
21802
+ * reason as `delete-outcome.ts`: the deploy engine, the drift-revert command
21803
+ * and the rollback executor all consume it, and those already sit on a dense
21804
+ * import ring. A helper that pulled anything else in would close it.
21805
+ */
21806
+ /**
21807
+ * The `reason` of a `'partial'` update outcome, or `undefined` when the
21808
+ * provider reported a clean update (`{ outcome: 'updated' }` or the
21809
+ * back-compat omission ~80 providers still use).
21810
+ *
21811
+ * A function rather than an inline `result.outcome === 'partial'` test at
21812
+ * three call sites, so the back-compat reading lives in ONE place — the same
21813
+ * call {@link ./delete-outcome.ts} made, and for the same reason: the arm is
21814
+ * optional, so a caller comparing by hand can silently test nothing.
21815
+ */
21816
+ function updatePartialReason(result) {
21817
+ if (!result || result.outcome !== "partial") return void 0;
21818
+ if (typeof result.reason !== "string") return UNSPECIFIED_PARTIAL_REASON;
21819
+ const trimmed = result.reason.trim();
21820
+ return trimmed === "" ? UNSPECIFIED_PARTIAL_REASON : trimmed;
21821
+ }
21822
+ /**
21823
+ * The one-line status suffix for a partial update, matching the destroy path's
21824
+ * `skipped (<reason>)` shape so the two verbs read the same way.
21825
+ *
21826
+ * Deliberately NOT the word `skipped`: the row's own resource WAS updated, and
21827
+ * `RESOURCE_SKIPPED`'s documented invariant is "the resource this row names was
21828
+ * not destroyed". Calling the row skipped would be false and would put the
21829
+ * event store at odds with its own contract.
21830
+ */
21831
+ /**
21832
+ * Stand-in for a `'partial'` outcome whose producer supplied no usable reason.
21833
+ *
21834
+ * Says the cause is unknown rather than inventing one: the row still has to
21835
+ * announce that something survived, and a confident-sounding wrong cause is
21836
+ * worse than an admitted gap.
21837
+ */
21838
+ const UNSPECIFIED_PARTIAL_REASON = "provider reported a partial update without a reason";
21839
+ function updatePartialMessage(reason) {
21840
+ return `partial (${reason})`;
21841
+ }
21842
+
21606
21843
  //#endregion
21607
21844
  //#region src/deployment/rollback-executor.ts
21608
21845
  /**
@@ -21869,13 +22106,14 @@ async function replayRollback(operations, stateResources, stackName, ctx, option
21869
22106
  eventType: "ROLLBACK_STARTED",
21870
22107
  stackName
21871
22108
  });
22109
+ const resolver = new IntrinsicFunctionResolver(ctx.region);
21872
22110
  const { createOps, otherOps } = partitionOps(operations);
21873
22111
  for (let i = otherOps.length - 1; i >= 0; i--) {
21874
22112
  if (options.isInterrupted?.()) {
21875
22113
  result.interrupted = true;
21876
22114
  break;
21877
22115
  }
21878
- await replaySingle(otherOps[i], stateResources, stackName, ctx, orphanLogicalIds, result, options.afterOp, options.isInterrupted);
22116
+ await replaySingle(otherOps[i], stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.afterOp, options.isInterrupted);
21879
22117
  }
21880
22118
  if (!result.interrupted && createOps.length > 0) {
21881
22119
  const sorted = sortRollbackCreates(createOps, stateResources);
@@ -21884,7 +22122,7 @@ async function replayRollback(operations, stateResources, stackName, ctx, option
21884
22122
  result.interrupted = true;
21885
22123
  break;
21886
22124
  }
21887
- await replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds, result, options.afterOp, options.isInterrupted);
22125
+ await replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.afterOp, options.isInterrupted);
21888
22126
  }
21889
22127
  }
21890
22128
  ctx.logger.info("Rollback completed. Some resources may remain if deletion failed.");
@@ -22064,10 +22302,9 @@ function recordAfterRollbackUpdate(restored, result) {
22064
22302
  function recordedPropertiesAfterReplayCreate(restored, result) {
22065
22303
  return result.effectiveProperties === void 0 ? restored.properties : { ...result.effectiveProperties };
22066
22304
  }
22067
- async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds, result, afterOp, isInterrupted) {
22305
+ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, afterOp, isInterrupted) {
22068
22306
  const action = classifyRollbackOp(op, stateResources, orphanLogicalIds);
22069
22307
  const { logger } = ctx;
22070
- const resolver = new IntrinsicFunctionResolver(ctx.region);
22071
22308
  /**
22072
22309
  * The route a CREATE-rollback arm resolved for this op (issue #1366) —
22073
22310
  * hoisted so the shared catch's ROLLBACK_RESOURCE_FAILED reports the route
@@ -22306,7 +22543,9 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
22306
22543
  currentProps ?? {}
22307
22544
  ], op.logicalId, logger, isInterrupted);
22308
22545
  stateResources[op.logicalId] = redactRollbackRecord(recordAfterRollbackUpdate(previousState, revertResult), secrets, previousState.properties);
22309
- logger.info(` Rollback: ${op.logicalId} restored successfully`);
22546
+ const rollbackPartial = updatePartialReason(revertResult);
22547
+ if (rollbackPartial !== void 0) logger.warn(` Rollback: ${op.logicalId} restored, ${updatePartialMessage(rollbackPartial)}`);
22548
+ else logger.info(` Rollback: ${op.logicalId} restored successfully`);
22310
22549
  await afterOp?.(op.logicalId);
22311
22550
  ctx.recordEvent?.({
22312
22551
  eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
@@ -22314,7 +22553,8 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
22314
22553
  operation: "UPDATE",
22315
22554
  logicalId: op.logicalId,
22316
22555
  resourceType: op.resourceType,
22317
- ...op.provisionedBy && { provisionedBy: op.provisionedBy }
22556
+ ...op.provisionedBy && { provisionedBy: op.provisionedBy },
22557
+ ...rollbackPartial !== void 0 && { reason: rollbackPartial }
22318
22558
  });
22319
22559
  return;
22320
22560
  }
@@ -22446,7 +22686,9 @@ async function replayFailedOperations(failedOps, stateResources, stackName, ctx,
22446
22686
  attemptedProps ?? {}
22447
22687
  ], op.logicalId, logger, options.isInterrupted);
22448
22688
  stateResources[op.logicalId] = redactRollbackRecord(recordAfterRollbackUpdate(prev, revertFailedResult), secrets, prev.properties);
22449
- logger.info(` Rollback: ${op.logicalId} reverted successfully`);
22689
+ const revertFailedPartial = updatePartialReason(revertFailedResult);
22690
+ if (revertFailedPartial !== void 0) logger.warn(` Rollback: ${op.logicalId} reverted, ${updatePartialMessage(revertFailedPartial)}`);
22691
+ else logger.info(` Rollback: ${op.logicalId} reverted successfully`);
22450
22692
  await options.afterOp?.(op.logicalId);
22451
22693
  ctx.recordEvent?.({
22452
22694
  eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
@@ -22454,7 +22696,8 @@ async function replayFailedOperations(failedOps, stateResources, stackName, ctx,
22454
22696
  operation: "UPDATE",
22455
22697
  logicalId: op.logicalId,
22456
22698
  resourceType: op.resourceType,
22457
- ...op.provisionedBy && { provisionedBy: op.provisionedBy }
22699
+ ...op.provisionedBy && { provisionedBy: op.provisionedBy },
22700
+ ...revertFailedPartial !== void 0 && { reason: revertFailedPartial }
22458
22701
  });
22459
22702
  break;
22460
22703
  }
@@ -22571,7 +22814,7 @@ const FLUSH_INTERVAL_MS = 2e3;
22571
22814
  const FLUSH_EVENT_THRESHOLD = 50;
22572
22815
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
22573
22816
  function getCdkdVersion() {
22574
- return "0.283.35";
22817
+ return "0.284.0";
22575
22818
  }
22576
22819
  /**
22577
22820
  * Generate a time-sortable unique run id, e.g.
@@ -23682,6 +23925,7 @@ var DeployEngine = class {
23682
23925
  updated: 0,
23683
23926
  deleted: 0,
23684
23927
  deleteSkipped: 0,
23928
+ updatePartial: 0,
23685
23929
  unchanged: Object.keys(currentState.resources).length,
23686
23930
  durationMs: Date.now() - startTime,
23687
23931
  outputs: this.buildDisplayOutputs(template, persistedOutputs),
@@ -23700,6 +23944,7 @@ var DeployEngine = class {
23700
23944
  updated: updateChanges.length,
23701
23945
  deleted: deleteChanges.length,
23702
23946
  deleteSkipped: 0,
23947
+ updatePartial: 0,
23703
23948
  unchanged: this.diffCalculator.filterByType(changes, "NO_CHANGE").length,
23704
23949
  durationMs: Date.now() - startTime,
23705
23950
  attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
@@ -23723,6 +23968,7 @@ var DeployEngine = class {
23723
23968
  updated: actualCounts.updated,
23724
23969
  deleted: actualCounts.deleted,
23725
23970
  deleteSkipped: actualCounts.deleteSkipped,
23971
+ updatePartial: actualCounts.updatePartial,
23726
23972
  unchanged: unchangedCount,
23727
23973
  durationMs,
23728
23974
  outputs: this.buildDisplayOutputs(template, newState.outputs ?? {}),
@@ -23757,7 +24003,8 @@ var DeployEngine = class {
23757
24003
  updated: 0,
23758
24004
  deleted: 0,
23759
24005
  skipped: 0,
23760
- deleteSkipped: 0
24006
+ deleteSkipped: 0,
24007
+ updatePartial: 0
23761
24008
  };
23762
24009
  const completedOperations = [];
23763
24010
  const failedOperations = [];
@@ -24176,9 +24423,14 @@ var DeployEngine = class {
24176
24423
  ...labelRouting && { provisionedBy: labelRouting }
24177
24424
  });
24178
24425
  let deleteSkipped;
24426
+ let updatePartial;
24427
+ const physicalIdBeforeUpdate = stateResources[logicalId]?.physicalId;
24428
+ const provisionedByBeforeUpdate = stateResources[logicalId]?.provisionedBy;
24179
24429
  try {
24180
24430
  await withResourceDeadline(async () => {
24181
- deleteSkipped = (await this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress))?.deleteSkipped;
24431
+ const bodyResult = await this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress);
24432
+ deleteSkipped = bodyResult?.deleteSkipped;
24433
+ updatePartial = bodyResult?.updatePartial;
24182
24434
  }, {
24183
24435
  warnAfterMs,
24184
24436
  timeoutMs,
@@ -24206,6 +24458,17 @@ var DeployEngine = class {
24206
24458
  });
24207
24459
  return { deleteSkipped };
24208
24460
  }
24461
+ if (updatePartial !== void 0) this.recordEvent({
24462
+ eventType: "RESOURCE_SKIPPED",
24463
+ stackName,
24464
+ operation: eventOp,
24465
+ logicalId,
24466
+ resourceType,
24467
+ ...provisionedByBeforeUpdate ? { provisionedBy: provisionedByBeforeUpdate } : labelRouting && { provisionedBy: labelRouting },
24468
+ ...physicalIdBeforeUpdate && { physicalId: physicalIdBeforeUpdate },
24469
+ reason: updatePartial,
24470
+ durationMs: Date.now() - resourceStartedAt
24471
+ });
24209
24472
  this.recordEvent({
24210
24473
  eventType: "RESOURCE_SUCCEEDED",
24211
24474
  stackName,
@@ -24637,10 +24900,16 @@ var DeployEngine = class {
24637
24900
  };
24638
24901
  const updateCaptureSiblings = await this.buildObservedCaptureSiblings(resourceType, logicalId, result.physicalId, template, stateResources, stackName, parameterValues, conditions);
24639
24902
  this.kickOffObservedCapture(updateProvider, logicalId, result.physicalId, resourceType, resolvedProps, updateCaptureSiblings);
24640
- if (counts) counts.updated++;
24903
+ const updatePartial = updatePartialReason(result);
24904
+ if (counts) if (updatePartial !== void 0) counts.updatePartial++;
24905
+ else counts.updated++;
24641
24906
  if (progress) progress.current++;
24642
24907
  const updatePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
24643
24908
  renderer.removeTask(logicalId);
24909
+ if (updatePartial !== void 0) {
24910
+ this.logger.warn(`${updatePrefix}${formatResourceLine("updated", logicalId, resourceType)} ` + updatePartialMessage(updatePartial));
24911
+ return { updatePartial };
24912
+ }
24644
24913
  this.logger.info(`${updatePrefix}${formatResourceLine("updated", logicalId, resourceType)}`);
24645
24914
  }
24646
24915
  break;
@@ -25012,5 +25281,5 @@ var DeployEngine = class {
25012
25281
  };
25013
25282
 
25014
25283
  //#endregion
25015
- export { getAccountInfo as $, SynthesisError as $n, formatDockerLoginError as $t, cyan as A, resolveBucketRegion as An, TemplateParser as At, stateKeySecretExposure as B, LocalInvokeBuildError as Bn, loadPublishableAssetManifest as Bt, makeCanonicalizePropertiesFn as C, expectedOwnerParam as Cn, s3BucketWebsiteUrl as Ct, renderStatefulReason as D, AssemblyReader as Dn, describeTypeWithThrottleRetry as Dt, isStatefulRecreateTargetSync as E, derivePartitionAndUrlSuffix as En, INTRINSIC_KEYS as Et, collectDeclaredOutputNames as F, AssetError as Fn, AssetPublisher as Ft, findActionableSilentDrops as G, NestedStackChildDirectDestroyError as Gn, BOOTSTRAP_MARKER_PREFIX as Gt, collectInlinePolicyNamesManagedBySiblings as H, LocalStartServiceError as Hn, escapeRegExp$1 as Ht, collectPublishedOutputNames as I, CdkdError as In, stringifyValue as It, slowCcOperationTimeoutMs as J, ResourceTimeoutError as Jn, parseBootstrapMarker as Jt, findSilentDropProperties as K, PartialFailureError as Kn, ensureAssetStorage as Kt, exportAliasCollisionScrubWarning as L, ConfigError as Ln, WorkGraph as Lt, green as M, getAwsClients as Mn, S3StateBackend as Mt, red as N, resetAwsClients as Nn, rebuildClientForBucketRegion as Nt, formatResourceLine as O, processStackMessages as On, withRetry as Ot, yellow as P, setAwsClients as Pn, shouldRetainResource as Pt, cfnRefValueFromPhysicalId as Q, StateError as Qn, buildDockerImage as Qt, isExportAliasCollision as R, DependencyError as Rn, buildAssetRedirectMap as Rt, unsupportedFinalSnapshotError as S, uploadCfnTemplate as Sn, s3BucketRegionalDomainName as St, MULTI_REGION_RECREATE_BLOCKED_TYPES as T, canonicalizeRegion as Tn, DiffCalculator as Tt, clearOnUpdateRemoval as U, LockError as Un, stripControlChars as Ut, IAMRoleProvider as V, LocalMigrateError as Vn, rewriteTemplateAssetReferences as Vt, ProviderRegistry as W, MissingCdkCliError as Wn, AssetModeResolver as Wt, isTerminationProtectionPropagationError as X, StackHasActiveImportsError as Xn, validateContainerRepoName as Xt, disableInstanceApiTermination as Y, ResourceUpdateNotSupportedError as Yn, validateAssetBucketName as Yt, IntrinsicFunctionResolver as Z, StackTerminationProtectionError as Zn, buildDenyExternalAccessPolicy as Zt, buildFinalSnapshotIdentifier as _, warnDeprecatedNoPrefixCliFlag as _n, redactSecretsForState as _t, DeploymentEventsStore as a, Synthesizer as an, isRetryableTransientError as ar, coerceCfnBoolean as at, isFinalSnapshotError as b, MIGRATE_TMP_PREFIX as bn, s3BucketDomainName as bt, replayFailedOperations as c, getLegacyStateBucketName as cn, __exportAll as cr, readConfigString as ct, deleteSkipReason as d, resolveCaptureObservedState as dn, requireConfigObject as dt, getDockerCmd as en, formatError as er, refStateLookupFromResource as et, withResourceDeadline as f, resolveSkipPrefix as fn, requireConfigString as ft, PRE_DELETE_SNAPSHOT_TYPES as g, stateBucketExistenceConfirmed as gn, maskSecretsInText as gt, ATOMIC_FINAL_SNAPSHOT_TYPES as h, resolveUseCdkBootstrapAssets as hn, TEMPLATE_SOURCED_RULES as ht, DeploymentEventsReader as i, getDockerImageBySourceHash as in, isMarkedNonRetryable as ir, assertRegionMatch as it, gray as j, AwsClients as jn, LockManager as jt, bold as k, clearBucketRegionCache as kn, DagBuilder as kt, replayRollback as l, resolveApp as ln, replayWarn as lt, computeImplicitDeleteEdges as m, resolveStateBucketWithDefaultAndSource as mn, STATE_SOURCED_READBACK_RULES as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, runDockerStreaming as nn, normalizeAwsError as nr, normalizeAwsTagsToCfn as nt, planFailedOps as o, synthesisStatusMessage as on, isThrottlingError as or, configBooleanRefusal as ot, IMPLICIT_DELETE_DEPENDENCIES as p, resolveStateBucketWithDefault as pn, STATE_SOURCED_CROSS_GENERATION_RULES as pt, CloudControlProvider as q, ProvisioningError as qn, getBootstrapMarkerKey as qt, DeployEngine as r, AssetManifestLoader as rn, withErrorHandling as rr, resolveExplicitPhysicalId as rt, planRollback as s, getDefaultStateBucketName as sn, markNonRetryable as sr, configStringRefusal as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, runDockerForeground as tn, isCdkdError as tr, WAFv2WebACLProvider as tt, UNSPECIFIED_SKIP_REASON as u, resolveAutoAssetStorage as un, requireConfigArray as ut, ccRoutedFinalSnapshotError as v, CFN_TEMPLATE_BODY_LIMIT as vn, scrubResourceRecord as vt, extractDeploymentEventError as w, PARTITION_TABLE as wn, applyRoleArnIfSet as wt, refusesFinalSnapshot as x, findLargeInlineResources as xn, s3BucketDualStackDomainName as xt, createPreDeleteFinalSnapshot as y, CFN_TEMPLATE_URL_LIMIT as yn, s3BucketArn as yt, secretBearingStateKeyWarning as z, DeployCancelledError as zn, createAssetRedirectResolver as zt };
25016
- //# sourceMappingURL=deploy-engine-fBYrdrmB.js.map
25284
+ export { IntrinsicFunctionResolver as $, StackTerminationProtectionError as $n, buildDenyExternalAccessPolicy as $t, formatResourceLine as A, processStackMessages as An, withRetry as At, isExportAliasCollision as B, DependencyError as Bn, buildAssetRedirectMap as Bt, refusesFinalSnapshot as C, findLargeInlineResources as Cn, s3BucketDualStackDomainName as Ct, MULTI_REGION_RECREATE_BLOCKED_TYPES as D, canonicalizeRegion as Dn, DiffCalculator as Dt, extractDeploymentEventError as E, PARTITION_TABLE as En, applyRoleArnIfSet as Et, red as F, resetAwsClients as Fn, rebuildClientForBucketRegion as Ft, clearOnUpdateRemoval as G, LockError as Gn, stripControlChars as Gt, stateKeySecretExposure as H, LocalInvokeBuildError as Hn, loadPublishableAssetManifest as Ht, yellow as I, setAwsClients as In, shouldRetainResource as It, findSilentDropProperties as J, PartialFailureError as Jn, ensureAssetStorage as Jt, ProviderRegistry as K, MissingCdkCliError as Kn, AssetModeResolver as Kt, collectDeclaredOutputNames as L, AssetError as Ln, AssetPublisher as Lt, cyan as M, resolveBucketRegion as Mn, TemplateParser as Mt, gray as N, AwsClients as Nn, LockManager as Nt, isStatefulRecreateTargetSync as O, derivePartitionAndUrlSuffix as On, INTRINSIC_KEYS as Ot, green as P, getAwsClients as Pn, S3StateBackend as Pt, isTerminationProtectionPropagationError as Q, StackHasActiveImportsError as Qn, validateContainerRepoName as Qt, collectPublishedOutputNames as R, CdkdError as Rn, stringifyValue as Rt, isFinalSnapshotError as S, MIGRATE_TMP_PREFIX as Sn, s3BucketDomainName as St, makeCanonicalizePropertiesFn as T, expectedOwnerParam as Tn, s3BucketWebsiteUrl as Tt, IAMRoleProvider as U, LocalMigrateError as Un, rewriteTemplateAssetReferences as Ut, secretBearingStateKeyWarning as V, DeployCancelledError as Vn, createAssetRedirectResolver as Vt, collectInlinePolicyNamesManagedBySiblings as W, LocalStartServiceError as Wn, escapeRegExp$1 as Wt, slowCcOperationTimeoutMs as X, ResourceTimeoutError as Xn, parseBootstrapMarker as Xt, CloudControlProvider as Y, ProvisioningError as Yn, getBootstrapMarkerKey as Yt, disableInstanceApiTermination as Z, ResourceUpdateNotSupportedError as Zn, validateAssetBucketName as Zt, ATOMIC_FINAL_SNAPSHOT_TYPES as _, resolveUseCdkBootstrapAssets as _n, TEMPLATE_SOURCED_RULES as _t, DeploymentEventsStore as a, AssetManifestLoader as an, withErrorHandling as ar, resolveExplicitPhysicalId as at, ccRoutedFinalSnapshotError as b, CFN_TEMPLATE_BODY_LIMIT as bn, scrubResourceRecord as bt, replayFailedOperations as c, synthesisStatusMessage as cn, isThrottlingError as cr, configBooleanRefusal as ct, updatePartialReason as d, resolveApp as dn, replayWarn as dt, buildDockerImage as en, StateError as er, cfnRefValueFromPhysicalId as et, UNSPECIFIED_SKIP_REASON as f, resolveAutoAssetStorage as fn, requireConfigArray as ft, computeImplicitDeleteEdges as g, resolveStateBucketWithDefaultAndSource as gn, STATE_SOURCED_READBACK_RULES as gt, IMPLICIT_DELETE_DEPENDENCIES as h, resolveStateBucketWithDefault as hn, STATE_SOURCED_CROSS_GENERATION_RULES as ht, DeploymentEventsReader as i, runDockerStreaming as in, normalizeAwsError as ir, normalizeAwsTagsToCfn as it, bold as j, clearBucketRegionCache as jn, DagBuilder as jt, renderStatefulReason as k, AssemblyReader as kn, describeTypeWithThrottleRetry as kt, replayRollback as l, getDefaultStateBucketName as ln, markNonRetryable as lr, configStringRefusal as lt, withResourceDeadline as m, resolveSkipPrefix as mn, requireConfigString as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, getDockerCmd as nn, formatError as nr, refStateLookupFromResource as nt, planFailedOps as o, getDockerImageBySourceHash as on, isMarkedNonRetryable as or, assertRegionMatch as ot, deleteSkipReason as p, resolveCaptureObservedState as pn, requireConfigObject as pt, findActionableSilentDrops as q, NestedStackChildDirectDestroyError as qn, BOOTSTRAP_MARKER_PREFIX as qt, DeployEngine as r, runDockerForeground as rn, isCdkdError as rr, WAFv2WebACLProvider as rt, planRollback as s, Synthesizer as sn, isRetryableTransientError as sr, coerceCfnBoolean as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, formatDockerLoginError as tn, SynthesisError as tr, getAccountInfo as tt, updatePartialMessage as u, getLegacyStateBucketName as un, __exportAll as ur, readConfigString as ut, PRE_DELETE_SNAPSHOT_TYPES as v, stateBucketExistenceConfirmed as vn, maskSecretsInText as vt, unsupportedFinalSnapshotError as w, uploadCfnTemplate as wn, s3BucketRegionalDomainName as wt, createPreDeleteFinalSnapshot as x, CFN_TEMPLATE_URL_LIMIT as xn, s3BucketArn as xt, buildFinalSnapshotIdentifier as y, warnDeprecatedNoPrefixCliFlag as yn, redactSecretsForState as yt, exportAliasCollisionScrubWarning as z, ConfigError as zn, WorkGraph as zt };
25285
+ //# sourceMappingURL=deploy-engine-C7JEL0Mg.js.map