@go-to-k/cdkd 0.285.5 → 0.285.7

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 { d as generateResourceName, f as generateResourceNameWithFallback, g as withStackName, m as looksLikeCdkdGeneratedName, n as getLogger, o as getLiveRenderer, p as getCurrentStackName, u as applyDefaultNameForFallback } from "./logger-Dz3Le2Pw.js";
1
+ import { _ as withStackName, d as applyDefaultNameForFallback, f as generateResourceName, h as looksLikeCdkdGeneratedName, m as getCurrentStackName, n as getLogger, p as generateResourceNameWithFallback, r as isStdoutReservedForPayload, s as getLiveRenderer } from "./logger-DyTk5GeO.js";
2
2
  import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
3
- import { t as getCdkdVersion } from "./version-neBHYAq9.js";
3
+ import { t as getCdkdVersion } from "./version-DlUEyyGa.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { randomUUID } from "node:crypto";
6
6
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -3880,6 +3880,44 @@ async function expectedOwnerParam(client) {
3880
3880
  return owner ? { ExpectedBucketOwner: owner } : {};
3881
3881
  }
3882
3882
 
3883
+ //#endregion
3884
+ //#region src/utils/display-safe.ts
3885
+ /**
3886
+ * Make an untrusted value safe to render in a terminal or persist into a log.
3887
+ *
3888
+ * A LEAF module with no imports, and deliberately in `src/utils/` rather than
3889
+ * beside its first caller: issue [#2170](https://github.com/go-to-k/cdkd/issues/2170)'s
3890
+ * review found the same rule being widened BY HAND one module at a time and
3891
+ * missing an instance every round — the change sanitized 1 of 5 readers of
3892
+ * `LockInfo.owner`. One shared definition, imported by everything that renders
3893
+ * such a value, is what stops the next reader from inheriting nothing.
3894
+ *
3895
+ * The stripped class is wider than C0 + DEL, which a first cut used and which
3896
+ * misses every mechanism that actually forges a line:
3897
+ *
3898
+ * - `U+0085` (NEL) and the C1 range — xterm reads `U+009B` as CSI in UTF-8;
3899
+ * - `U+2028` / `U+2029` — this text is PERSISTED and re-rendered by JSON and
3900
+ * web log viewers, where both are line terminators;
3901
+ * - `U+202A`-`U+202E` / `U+2066`-`U+2069` — the Trojan-Source bidi overrides
3902
+ * and isolates, which visually REORDER the command being pasted.
3903
+ *
3904
+ * Known residual, recorded rather than implied away: the invisible formatters
3905
+ * (`U+200B`-`U+200D`, `U+FEFF`) and the bidi MARKS (`U+200E` / `U+200F` /
3906
+ * `U+061C`) survive, as do bare RTL letters, which no denylist can reach. All
3907
+ * of them can only make a rendered name differ visually from its bytes — the
3908
+ * command a user pastes still acts on exactly what is shown, and the blast
3909
+ * radius stays the attacker's own stack name.
3910
+ *
3911
+ * A caller whose value has a KNOWN ASCII charset (a stack name, an AWS region)
3912
+ * should pass `asciiOnly`, which is a positive allowlist and therefore has no
3913
+ * such residual at all.
3914
+ */
3915
+ function displaySafe(value, opts) {
3916
+ if (value === void 0 || value === null) return "";
3917
+ const text = String(value);
3918
+ return (opts?.asciiOnly ? text.replace(/[^ -~]/g, " ") : text.replace(/[\u0000-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e\u2066-\u2069]/g, " ")).trim();
3919
+ }
3920
+
3883
3921
  //#endregion
3884
3922
  //#region src/state/s3-noncurrent-version-purge.ts
3885
3923
  /**
@@ -3971,7 +4009,7 @@ async function purgeNoncurrentKeyVersions(s3Client, bucket, keys, options = {})
3971
4009
  for (const key of affected) recordFailure(failed, key, describe$1(error));
3972
4010
  }
3973
4011
  if (failed.size > 0) {
3974
- const named = [...failed.entries()].slice(0, MAX_NAMED_FAILURES).map(([key, reasons]) => `${key} (${reasons.join("; ")})`);
4012
+ const named = [...failed.entries()].slice(0, MAX_NAMED_FAILURES).map(([key, reasons]) => displaySafe(`${key} (${reasons.join("; ")})`));
3975
4013
  const elided = failed.size - named.length;
3976
4014
  logger.warn(`Could not purge noncurrent versions of ${failed.size} key(s) in s3://${bucket}. Their previous versions survive and remain readable via GetObject with a VersionId (${options.objectDescription ?? DEFAULT_OBJECT_DESCRIPTION}). Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key(s) by hand. Failures: ${named.join(", ")}` + (elided > 0 ? ` (and ${elided} more)` : ""));
3977
4015
  }
@@ -4023,6 +4061,7 @@ async function purgeUnderPrefix(s3Client, bucket, prefix, wanted, requestFields,
4023
4061
  }
4024
4062
  }));
4025
4063
  for (const err of deleted.Errors ?? []) {
4064
+ if (err.Code === "NoSuchVersion") continue;
4026
4065
  const reason = `version ${err.VersionId ?? "<unknown>"}: ${err.Code ?? "Error"}` + (err.Message ? ` - ${err.Message}` : "");
4027
4066
  if (err.Key !== void 0) recordFailure(failed, err.Key, reason);
4028
4067
  else {
@@ -5525,8 +5564,13 @@ var FileAssetPublisher = class {
5525
5564
  * Output handling: stdout/stderr are collected in memory unconditionally so
5526
5565
  * `runDockerStreaming` can return them to the caller for error wrapping.
5527
5566
  * When the logger is at debug level (i.e. the user passed `--verbose`),
5528
- * the chunks are ALSO mirrored to `process.stdout` / `process.stderr` so
5529
- * the user sees live build progress.
5567
+ * the chunks are ALSO mirrored live so the user sees build progress —
5568
+ * stderr always to `process.stderr`, and stdout to `process.stdout` EXCEPT
5569
+ * while a command holds a payload reservation
5570
+ * ({@link isStdoutReservedForPayload}), where it joins the logger on stderr
5571
+ * so a child's diagnostics cannot land in the payload
5572
+ * ([#2410](https://github.com/go-to-k/cdkd/issues/2410)). The same
5573
+ * reservation redirects `spawnForeground`'s inherited fd 1 to fd 2.
5530
5574
  */
5531
5575
  /**
5532
5576
  * Return the docker-compatible CLI binary to invoke. Matches CDK CLI:
@@ -5573,7 +5617,8 @@ async function spawnStreaming(cmd, args, options = {}) {
5573
5617
  const stderrChunks = [];
5574
5618
  child.stdout.on("data", (chunk) => {
5575
5619
  stdoutChunks.push(chunk);
5576
- if (streamLive) process.stdout.write(chunk);
5620
+ if (streamLive) if (isStdoutReservedForPayload()) process.stderr.write(chunk);
5621
+ else process.stdout.write(chunk);
5577
5622
  });
5578
5623
  child.stderr.on("data", (chunk) => {
5579
5624
  stderrChunks.push(chunk);
@@ -5617,25 +5662,42 @@ async function spawnStreaming(cmd, args, options = {}) {
5617
5662
  * exit, so the caller can wrap with its own error class.
5618
5663
  *
5619
5664
  * Differs from {@link runDockerStreaming} in two ways:
5620
- * 1. `stdio: 'inherit'` — output is NOT captured, so terminal control codes
5621
- * (color, progress bar overwrites) flow through unchanged. This is the
5622
- * load-bearing reason for the split: `docker pull`'s progress bars only
5623
- * animate properly when stdout is a real TTY connected to the parent.
5665
+ * 1. The child INHERITS descriptors — output is NOT captured, so terminal
5666
+ * control codes (color, progress bar overwrites) flow through
5667
+ * unchanged. That is the load-bearing reason for the split:
5668
+ * `docker pull`'s progress bars only animate when the child writes to a
5669
+ * real TTY rather than a pipe. Under a payload reservation the child's
5670
+ * fd 1 is redirected to the parent's fd 2 rather than piped, precisely
5671
+ * so it keeps a descriptor and not a pipe — though the animation then
5672
+ * depends on STDERR being a terminal, and degrades to plain lines under
5673
+ * `2> file` (issue
5674
+ * [#2410](https://github.com/go-to-k/cdkd/issues/2410)).
5624
5675
  * 2. No `input` / `streamLive` options — inherit-mode has nothing to
5625
5676
  * capture and nothing to mirror.
5626
5677
  *
5627
- * Used by the `--verbose`-mode `docker pull` plumbing in `docker-runner.ts`
5628
- * and `ecr-puller.ts` (visible layer progress). Non-verbose pulls go through
5629
- * {@link runDockerStreaming} so stderr can be folded into the error message.
5678
+ * Used by the `docker pull` plumbing in `docker-runner.ts` and
5679
+ * `ecr-puller.ts`. Those two callers differ, and the difference matters
5680
+ * enough to state: `docker-runner.ts` reaches this only under `--verbose`,
5681
+ * while `ecr-puller.ts` runs it UNCONDITIONALLY, which is what made the
5682
+ * pre-#2410 stdout leak reachable with no flag at all. Non-verbose pulls in
5683
+ * `docker-runner.ts` go through {@link runDockerStreaming} instead, so
5684
+ * stderr can be folded into the error message.
5630
5685
  */
5631
5686
  async function runDockerForeground(args, options = {}) {
5632
5687
  return spawnForeground(getDockerCmd(), args, options);
5633
5688
  }
5634
5689
  /**
5635
- * Foreground (stdio-inherit) spawn — the inherit-mode counterpart to
5690
+ * Foreground (descriptor-inheriting) spawn — the inherit-mode counterpart to
5636
5691
  * {@link spawnStreaming}. Used by {@link runDockerForeground} for docker-CLI
5637
5692
  * subprocesses.
5638
5693
  *
5694
+ * "inherit" is not unqualified, and THIS is the function that qualifies it:
5695
+ * while a command holds a payload reservation
5696
+ * ({@link isStdoutReservedForPayload}) the child's fd 1 is redirected to the
5697
+ * parent's fd 2, so its output cannot land in the payload
5698
+ * ([#2410](https://github.com/go-to-k/cdkd/issues/2410)). stdin and stderr
5699
+ * are inherited either way. See the inline note at the `spawn` call.
5700
+ *
5639
5701
  * The ENOENT branch crafts a docker-specific install hint ("Install Docker
5640
5702
  * (or set CDK_DOCKER ...)"), so non-docker callers reusing this helper
5641
5703
  * would see a misleading error on missing-binary failures. Keep the binary
@@ -5648,7 +5710,11 @@ async function spawnForeground(cmd, args, options = {}) {
5648
5710
  const child = spawn(cmd, args, {
5649
5711
  cwd: options.cwd,
5650
5712
  env,
5651
- stdio: "inherit"
5713
+ stdio: isStdoutReservedForPayload() ? [
5714
+ "inherit",
5715
+ 2,
5716
+ "inherit"
5717
+ ] : "inherit"
5652
5718
  });
5653
5719
  child.once("error", (err) => {
5654
5720
  if (err.code === "ENOENT") {
@@ -8665,44 +8731,6 @@ function isNoSuchKey(error) {
8665
8731
  return error?.name === "NoSuchKey";
8666
8732
  }
8667
8733
 
8668
- //#endregion
8669
- //#region src/utils/display-safe.ts
8670
- /**
8671
- * Make an untrusted value safe to render in a terminal or persist into a log.
8672
- *
8673
- * A LEAF module with no imports, and deliberately in `src/utils/` rather than
8674
- * beside its first caller: issue [#2170](https://github.com/go-to-k/cdkd/issues/2170)'s
8675
- * review found the same rule being widened BY HAND one module at a time and
8676
- * missing an instance every round — the change sanitized 1 of 5 readers of
8677
- * `LockInfo.owner`. One shared definition, imported by everything that renders
8678
- * such a value, is what stops the next reader from inheriting nothing.
8679
- *
8680
- * The stripped class is wider than C0 + DEL, which a first cut used and which
8681
- * misses every mechanism that actually forges a line:
8682
- *
8683
- * - `U+0085` (NEL) and the C1 range — xterm reads `U+009B` as CSI in UTF-8;
8684
- * - `U+2028` / `U+2029` — this text is PERSISTED and re-rendered by JSON and
8685
- * web log viewers, where both are line terminators;
8686
- * - `U+202A`-`U+202E` / `U+2066`-`U+2069` — the Trojan-Source bidi overrides
8687
- * and isolates, which visually REORDER the command being pasted.
8688
- *
8689
- * Known residual, recorded rather than implied away: the invisible formatters
8690
- * (`U+200B`-`U+200D`, `U+FEFF`) and the bidi MARKS (`U+200E` / `U+200F` /
8691
- * `U+061C`) survive, as do bare RTL letters, which no denylist can reach. All
8692
- * of them can only make a rendered name differ visually from its bytes — the
8693
- * command a user pastes still acts on exactly what is shown, and the blast
8694
- * radius stays the attacker's own stack name.
8695
- *
8696
- * A caller whose value has a KNOWN ASCII charset (a stack name, an AWS region)
8697
- * should pass `asciiOnly`, which is a positive allowlist and therefore has no
8698
- * such residual at all.
8699
- */
8700
- function displaySafe(value, opts) {
8701
- if (value === void 0 || value === null) return "";
8702
- const text = String(value);
8703
- return (opts?.asciiOnly ? text.replace(/[^ -~]/g, " ") : text.replace(/[\u0000-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e\u2066-\u2069]/g, " ")).trim();
8704
- }
8705
-
8706
8734
  //#endregion
8707
8735
  //#region src/state/lock-manager.ts
8708
8736
  /**
@@ -8726,6 +8754,15 @@ const RENEWAL_TTL_FRACTION = 4;
8726
8754
  /** Floor, so a pathologically small TTL cannot spin the event loop. */
8727
8755
  const MIN_RENEWAL_INTERVAL_MS = 1e3;
8728
8756
  /**
8757
+ * What a surviving `lock.json` version holds, for the purge warning's
8758
+ * parenthetical.
8759
+ *
8760
+ * The helper makes this per-caller precisely so a reader chasing the warning is
8761
+ * told which object to go and inspect; `lock.json` is the one call site whose
8762
+ * content is NOT a secret, and saying so is more useful than a vague phrase.
8763
+ */
8764
+ const LOCK_OBJECT_DESCRIPTION = "a stack lock heartbeat, which records the lock owner, its acquisition timestamp, its deadline and the operation name — no secret, but one row per renewal";
8765
+ /**
8729
8766
  * S3-based lock manager using conditional writes (If-None-Match)
8730
8767
  *
8731
8768
  * Implements distributed locking using S3's If-None-Match: "*" condition
@@ -8924,6 +8961,8 @@ var LockManager = class {
8924
8961
  return false;
8925
8962
  }
8926
8963
  throw retryError;
8964
+ } finally {
8965
+ await this.purgeLockVersions(key, "reap");
8927
8966
  }
8928
8967
  }
8929
8968
  return false;
@@ -9097,6 +9136,8 @@ var LockManager = class {
9097
9136
  }
9098
9137
  }
9099
9138
  throw new LockError(`Failed to release lock for stack '${stackName}' (${region}): ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : void 0);
9139
+ } finally {
9140
+ await this.purgeLockVersions(this.getLockKey(stackName, region), "release");
9100
9141
  }
9101
9142
  }
9102
9143
  /**
@@ -9160,12 +9201,17 @@ var LockManager = class {
9160
9201
  const where = `${stackName}${region ? ` (${region})` : ""}`;
9161
9202
  const lockInfo = await this.getLockInfo(stackName, region).catch(() => null);
9162
9203
  this.logger.warn(lockInfo ? `Force releasing lock for stack: ${where}, owner: ${lockInfo.owner}${lockInfo.operation ? `, operation: ${lockInfo.operation}` : ""}, expired: ${this.isLockExpired(lockInfo)}` : `Force releasing lock for stack: ${where} (no lock body read — absent or unparseable; deleting the object either way, since a lock cdkd cannot read is a lock nothing else can clear)`);
9163
- const held = this.heldLocks.get(this.getLockKey(stackName, region));
9204
+ const key = this.getLockKey(stackName, region);
9205
+ const held = this.heldLocks.get(key);
9164
9206
  if (held) {
9165
9207
  this.stopRenewal(held);
9166
9208
  held.releasing = Promise.resolve();
9167
9209
  }
9168
- await this.deleteLock(stackName, region);
9210
+ try {
9211
+ await this.deleteLock(stackName, region);
9212
+ } finally {
9213
+ await this.purgeLockVersions(key, "reap");
9214
+ }
9169
9215
  }
9170
9216
  /**
9171
9217
  * Internal method to delete the lock file from S3.
@@ -9175,6 +9221,17 @@ var LockManager = class {
9175
9221
  * caller read or wrote. S3 evaluates the condition against the CURRENT
9176
9222
  * version, which is the right unit here even on the versioned state bucket:
9177
9223
  * the current version IS the live lock.
9224
+ *
9225
+ * EVERY CALLER MUST PAIR THIS WITH {@link purgeLockVersions} (issue
9226
+ * [#2346](https://github.com/go-to-k/cdkd/issues/2346) site 5). The delete
9227
+ * writes a DELETE MARKER on the versioned state bucket and leaves every
9228
+ * prior body readable, so a delete on its own grows the key forever. The
9229
+ * purge is NOT folded in here, for two reasons that are both per-call-site:
9230
+ * the log level differs (see {@link LockPurgePath}), and the takeover path
9231
+ * must purge AFTER its re-acquisition PUT rather than immediately after the
9232
+ * delete. `tests/unit/state/lock-noncurrent-version-purge.test.ts` parses
9233
+ * this file and fails if a caller of this method does not also call the
9234
+ * purge, so a fifth call site cannot quietly skip it.
9178
9235
  */
9179
9236
  async deleteLock(stackName, region, etag) {
9180
9237
  await this.ensureClientForBucket();
@@ -9187,6 +9244,98 @@ var LockManager = class {
9187
9244
  }));
9188
9245
  }
9189
9246
  /**
9247
+ * Delete the lock key's NONCURRENT versions after a delete marker has been
9248
+ * landed on it (issue [#2346](https://github.com/go-to-k/cdkd/issues/2346)
9249
+ * site 5).
9250
+ *
9251
+ * ## Why the lock key needs this at all
9252
+ *
9253
+ * `cdkd bootstrap` turns VERSIONING ON for the state bucket, so
9254
+ * {@link deleteLock} writes a delete marker and every earlier body stays
9255
+ * readable through `GetObject` with a `VersionId`. Renewal writes one version
9256
+ * every {@link MAX_RENEWAL_INTERVAL_MS} (2 minutes at the default 30-minute
9257
+ * TTL, so a 30-minute deploy mints about fifteen), `deleteState` never
9258
+ * sweeps the lock key, and nothing else ever did — so the chain was
9259
+ * monotonic in stacks EVER deployed. 452 versions were measured on a single
9260
+ * key. Nothing in a `LockInfo` is a secret, so this is bucket cost and
9261
+ * listing noise rather than disclosure; it is still unbounded.
9262
+ *
9263
+ * ## Why the SHARED helper, and why that is safe on a lock
9264
+ *
9265
+ * A per-`VersionId` scheme (remember what this process minted, delete
9266
+ * exactly that) was designed and REJECTED on review. Its hazards were all
9267
+ * created by the mechanism: deleting one's OWN delete marker resurrects a
9268
+ * stale lock whenever a batch partially fails, a per-id delete has no
9269
+ * `IsLatest` guard so it can remove the CURRENT version on a refusal branch,
9270
+ * a `"null"` version id under suspended versioning is a legal delete target,
9271
+ * and the 1000-entry `DeleteObjects` cap forces a re-implementation of the
9272
+ * shared helper's batching. The shared helper's `IsLatest` filter removes
9273
+ * every one of them: it can never touch what is current, which is exactly
9274
+ * the live lock — ours or anyone else's.
9275
+ *
9276
+ * That filter is also what makes it correct to run this from a `finally`,
9277
+ * including on the arms where the delete was REFUSED. Purging noncurrent
9278
+ * versions while our own lock is still the current one is harmless.
9279
+ *
9280
+ * ## Level, and the one UX regression this avoids
9281
+ *
9282
+ * The four sites already purging (rollback journal, bootstrap marker,
9283
+ * transient template, custom-resource response) all warn, because what
9284
+ * survives there may be a secret and they fire on rare paths. `lock.json` is
9285
+ * neither: it holds no secret and `'release'` fires at the tail of EVERY
9286
+ * mutating command. Inheriting WARN would mean a user on the pre-#2340
9287
+ * four-action IAM policy starts seeing a warning after every single command,
9288
+ * about bucket tidiness. Be precise about WHICH user that is: a principal
9289
+ * missing `s3:ListBucketVersions` already gets a warn on every successful
9290
+ * deploy from `deleteRollbackJournal`'s purge, so nothing changes for them.
9291
+ * The one this split protects is the principal who HAS `ListBucketVersions`
9292
+ * but lacks `s3:DeleteObjectVersion` — silent today, and newly noisy without
9293
+ * it. So
9294
+ * release-path failures go to `debug` and only the rare `'reap'` paths warn,
9295
+ * which is the cost profile `docs/state-management.md` means by "only the
9296
+ * cleanup paths that need them".
9297
+ *
9298
+ * A warn-once-per-process dedupe was the other option and is not taken, for
9299
+ * the reason `s3-noncurrent-version-purge.ts` gives for rejecting one: it
9300
+ * needs module-global state, which this repo has been bitten by under
9301
+ * `--stack-concurrency > 1`.
9302
+ *
9303
+ * NEVER THROWS. The helper guarantees that for itself, but
9304
+ * `ensureClientForBucket()` and `ownerParam()` sit outside it, so the wrap
9305
+ * below is what makes the contract true. Only `ensureClientForBucket()` is a
9306
+ * known rejector (`GetBucketLocation`); `ownerParam()` is NOT — an earlier
9307
+ * revision claimed it reached STS, and `src/cli/upload-cfn-template.ts`
9308
+ * records that as false, since `resolveExpectedBucketOwner` wraps every
9309
+ * await and degrades to `undefined`. Naming an unproved mechanism is worse
9310
+ * than naming none. The wrap stays because a caller-supplied logger can
9311
+ * throw and because a future edit can add an awaited call here — the same
9312
+ * reasoning as
9313
+ * `S3StateBackend.purgeNoncurrentVersions`. It matters more here than there:
9314
+ * every call site is a `finally`, and a throw from a `finally` REPLACES the
9315
+ * `LockError` the release was raising. Nothing on this path is
9316
+ * interrupt-aware (`LockManager` starts no interrupt watch and issues no
9317
+ * `withRetry`), so there is no `InterruptedWaitError` for the swallow below
9318
+ * to hide.
9319
+ */
9320
+ async purgeLockVersions(key, path) {
9321
+ const report = (message) => {
9322
+ try {
9323
+ if (path === "reap") this.logger.warn(message);
9324
+ else this.logger.debug(message);
9325
+ } catch {}
9326
+ };
9327
+ try {
9328
+ await this.ensureClientForBucket();
9329
+ await purgeNoncurrentKeyVersions(this.s3Client, this.config.bucket, [key], {
9330
+ requestFields: await this.ownerParam(),
9331
+ logger: { warn: report },
9332
+ objectDescription: LOCK_OBJECT_DESCRIPTION
9333
+ });
9334
+ } catch (error) {
9335
+ report(`Could not purge noncurrent versions of the lock key '${displaySafe(key)}' in bucket '${this.config.bucket}': the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId (${LOCK_OBJECT_DESCRIPTION}). Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key by hand. Underlying error: ${error instanceof Error ? error.message : String(error)}`);
9336
+ }
9337
+ }
9338
+ /**
9190
9339
  * Record a lock this process now holds and start renewing it.
9191
9340
  */
9192
9341
  trackHeldLock(args) {
@@ -21313,7 +21462,7 @@ var CloudControlProvider = class {
21313
21462
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
21314
21463
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
21315
21464
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
21316
- const { ASGProvider } = await import("./asg-provider-BBSPZtne.js").then((n) => n.n);
21465
+ const { ASGProvider } = await import("./asg-provider-B1EEjygi.js").then((n) => n.n);
21317
21466
  return withIndeterminateGuard(await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
21318
21467
  }
21319
21468
  const isProtectedEc2Instance = context?.removeProtection === true && resourceType === "AWS::EC2::Instance";
@@ -33257,5 +33406,5 @@ var DeployEngine = class {
33257
33406
  };
33258
33407
 
33259
33408
  //#endregion
33260
- export { DEFAULT_STATE_PREFIX as $, warnDeprecatedNoPrefixCliFlag as $n, maskSecretsInError as $t, bold as A, buildDenyExternalAccessPolicy as An, NestedStackChildDirectDestroyError as Ar, requireConfigObject as At, secretBearingStateKeyWarning as B, getDockerImageBySourceHash as Bn, isCdkdError as Br, DiffCalculator as Bt, unsupportedFinalSnapshotError as C, ensureAssetStorage as Cn, DeployCancelledError as Cr, assertRegionMatch as Ct, isStatefulRecreateTargetSync as D, readBootstrapMarkerBody as Dn, LocalStartServiceError as Dr, readConfigString as Dt, MULTI_REGION_RECREATE_BLOCKED_TYPES as E, parseBootstrapMarker as En, LocalMigrateError as Er, configStringRefusal as Et, yellow as F, getDockerCmd as Fn, StackHasActiveImportsError as Fr, s3BucketDomainName as Ft, clearOnUpdateRemoval as G, resolveApp as Gn, isThrottlingError as Gr, TemplateParser as Gt, getCurrentResourceSecrets as H, synthesisStatusMessage as Hn, withErrorHandling as Hr, describeTypeWithThrottleRetry as Ht, collectDeclaredOutputNames as I, partitionSensitiveEnv as In, StackTerminationProtectionError as Ir, s3BucketDualStackDomainName as It, findSilentDropProperties as J, resolveSkipPrefix as Jn, markRedactedCause as Jr, TEMPLATE_SOURCED_RULES as Jt, ProviderRegistry as K, resolveAutoAssetStorage as Kn, isTransientServerError as Kr, STATE_SOURCED_CROSS_GENERATION_RULES as Kt, collectPublishedOutputNames as L, runDockerForeground as Ln, StateError as Lr, s3BucketRegionalDomainName as Lt, gray as M, buildDockerImage as Mn, ProvisioningError as Mr, classifyReplaySecretRegion as Mt, green as N, dockerSpawnEnvWithSensitive as Nn, ResourceTimeoutError as Nr, producerRegionsFromState as Nt, renderStatefulReason as O, validateAssetBucketName as On, LockError as Or, replayWarn as Ot, red as P, formatDockerLoginError as Pn, ResourceUpdateNotSupportedError as Pr, s3BucketArn as Pt, CUSTOM_RESOURCE_RESPONSE_PREFIX as Q, stateBucketExistenceConfirmed as Qn, isSingleDynamicReferenceToken as Qt, exportAliasCollisionScrubWarning as R, runDockerStreaming as Rn, SynthesisError as Rr, s3BucketWebsiteUrl as Rt, refusesFinalSnapshot as S, assertAssetBucketRegion as Sn, DependencyError as Sr, resolveExplicitPhysicalId as St, extractDeploymentEventError as T, isCrossRegionRedirect as Tn, LocalInvokeBuildError as Tr, configBooleanRefusal as Tt, IAMRoleProvider as U, getDefaultStateBucketName as Un, isMarkedNonRetryable as Ur, withRetry as Ut, stateKeySecretExposure as V, Synthesizer as Vn, normalizeAwsError as Vr, INTRINSIC_KEYS as Vt, collectInlinePolicyNamesManagedBySiblings as W, getLegacyStateBucketName as Wn, isRetryableTransientError as Wr, DagBuilder as Wt, maskDeep as X, resolveStateBucketWithDefaultAndSource as Xn, __exportAll as Xr, dynamicReferenceTokens as Xt, createMaskedRetryLogger as Y, resolveStateBucketWithDefault as Yn, retryClassificationText as Yr, createSecretMasker as Yt, maskerOrIdentity as Z, resolveUseCdkBootstrapAssets as Zn, errorCauseChain as Zt, PRE_DELETE_SNAPSHOT_TYPES as _, rewriteTemplateAssetReferences as _n, setAwsClients as _r, isUnboundTemplateParameter as _t, DeploymentEventsStore as a, S3StateBackend as an, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as ar, CloudControlProvider as at, createPreDeleteFinalSnapshot as b, AssetModeResolver as bn, ConfigError as br, WAFv2WebACLProvider as bt, replayFailedOperations as c, importableOutputKeys as cn, canonicalizeRegion as cr, deleteIndeterminateGuards as ct, updatePartialReason as d, AssetPublisher as dn, processStackMessages as dr, isTerminationProtectionPropagationError as dt, maskSecretsInText as en, CFN_TEMPLATE_BODY_LIMIT as er, beginCommandInterruptScope as et, withResourceDeadline as f, stringifyValue as fn, clearBucketRegionCache as fr, IntrinsicFunctionResolver as ft, ATOMIC_FINAL_SNAPSHOT_TYPES as g, loadPublishableAssetManifest as gn, resetAwsClients as gr, getAccountInfo as gt, computeImplicitDeleteEdges as h, createAssetRedirectResolver as hn, getAwsClients as hr, coerceParameterTypedValue as ht, DeploymentEventsReader as i, displaySafe as in, uploadCfnTemplate as ir, startInterruptWatch as it, cyan as j, describeAwsFailure as jn, PartialFailureError as jr, requireConfigString as jt, formatResourceLine as k, validateContainerRepoName as kn, MissingCdkCliError as kr, requireConfigArray as kt, replayRollback as l, importableOutputs as ln, derivePartitionAndUrlSuffix as lr, deleteSkipReason as lt, IMPLICIT_DELETE_DEPENDENCIES as m, buildAssetRedirectMap as mn, AwsClients as mr, cfnRefValueFromPhysicalId as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, scrubResourceRecord as nn, MIGRATE_TMP_PREFIX as nr, interruptWatchListenerCount as nt, planFailedOps as o, rebuildClientForBucketRegion as on, expectedOwnerParam as or, slowCcOperationTimeoutMs as ot, maskingRetryLogger as p, WorkGraph as pn, resolveBucketRegion as pr, carriesDynamicReference as pt, findActionableSilentDrops as q, resolveCaptureObservedState as qn, markNonRetryable as qr, STATE_SOURCED_READBACK_RULES as qt, DeployEngine as r, LockManager as rn, findLargeInlineResources as rr, isInterruptedWaitError as rt, planRollback as s, exportNamesCarriedFrom as sn, PARTITION_TABLE as sr, UNSPECIFIED_SKIP_REASON as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, redactSecretsForState as tn, CFN_TEMPLATE_URL_LIMIT as tr, endCommandInterruptScope as tt, updatePartialMessage as u, shouldRetainResource as un, AssemblyReader as ur, disableInstanceApiTermination as ut, buildFinalSnapshotIdentifier as v, escapeRegExp$1 as vn, AssetError as vr, parameterTypeMayLoseSecretIdentity as vt, makeCanonicalizePropertiesFn as w, getBootstrapMarkerKey as wn, DynamicReferenceRegionAmbiguousError as wr, coerceCfnBoolean as wt, isFinalSnapshotError as x, BOOTSTRAP_MARKER_PREFIX as xn, CrossAccountSecretRefusalError as xr, normalizeAwsTagsToCfn as xt, ccRoutedFinalSnapshotError as y, stripControlChars as yn, CdkdError as yr, refStateLookupFromResource as yt, isExportAliasCollision as z, AssetManifestLoader as zn, formatError as zr, applyRoleArnIfSet as zt };
33261
- //# sourceMappingURL=deploy-engine-CSBoL-Az.js.map
33409
+ export { DEFAULT_STATE_PREFIX as $, CFN_TEMPLATE_BODY_LIMIT as $n, maskSecretsInError as $t, bold as A, describeAwsFailure as An, NestedStackChildDirectDestroyError as Ar, requireConfigObject as At, secretBearingStateKeyWarning as B, Synthesizer as Bn, isCdkdError as Br, DiffCalculator as Bt, unsupportedFinalSnapshotError as C, getBootstrapMarkerKey as Cn, DeployCancelledError as Cr, assertRegionMatch as Ct, isStatefulRecreateTargetSync as D, validateAssetBucketName as Dn, LocalStartServiceError as Dr, readConfigString as Dt, MULTI_REGION_RECREATE_BLOCKED_TYPES as E, readBootstrapMarkerBody as En, LocalMigrateError as Er, configStringRefusal as Et, yellow as F, partitionSensitiveEnv as Fn, StackHasActiveImportsError as Fr, s3BucketDomainName as Ft, clearOnUpdateRemoval as G, resolveAutoAssetStorage as Gn, isThrottlingError as Gr, TemplateParser as Gt, getCurrentResourceSecrets as H, getDefaultStateBucketName as Hn, withErrorHandling as Hr, describeTypeWithThrottleRetry as Ht, collectDeclaredOutputNames as I, runDockerForeground as In, StackTerminationProtectionError as Ir, s3BucketDualStackDomainName as It, findSilentDropProperties as J, resolveStateBucketWithDefault as Jn, markRedactedCause as Jr, TEMPLATE_SOURCED_RULES as Jt, ProviderRegistry as K, resolveCaptureObservedState as Kn, isTransientServerError as Kr, STATE_SOURCED_CROSS_GENERATION_RULES as Kt, collectPublishedOutputNames as L, runDockerStreaming as Ln, StateError as Lr, s3BucketRegionalDomainName as Lt, gray as M, dockerSpawnEnvWithSensitive as Mn, ProvisioningError as Mr, classifyReplaySecretRegion as Mt, green as N, formatDockerLoginError as Nn, ResourceTimeoutError as Nr, producerRegionsFromState as Nt, renderStatefulReason as O, validateContainerRepoName as On, LockError as Or, replayWarn as Ot, red as P, getDockerCmd as Pn, ResourceUpdateNotSupportedError as Pr, s3BucketArn as Pt, CUSTOM_RESOURCE_RESPONSE_PREFIX as Q, warnDeprecatedNoPrefixCliFlag as Qn, isSingleDynamicReferenceToken as Qt, exportAliasCollisionScrubWarning as R, AssetManifestLoader as Rn, SynthesisError as Rr, s3BucketWebsiteUrl as Rt, refusesFinalSnapshot as S, ensureAssetStorage as Sn, DependencyError as Sr, resolveExplicitPhysicalId as St, extractDeploymentEventError as T, parseBootstrapMarker as Tn, LocalInvokeBuildError as Tr, configBooleanRefusal as Tt, IAMRoleProvider as U, getLegacyStateBucketName as Un, isMarkedNonRetryable as Ur, withRetry as Ut, stateKeySecretExposure as V, synthesisStatusMessage as Vn, normalizeAwsError as Vr, INTRINSIC_KEYS as Vt, collectInlinePolicyNamesManagedBySiblings as W, resolveApp as Wn, isRetryableTransientError as Wr, DagBuilder as Wt, maskDeep as X, resolveUseCdkBootstrapAssets as Xn, __exportAll as Xr, dynamicReferenceTokens as Xt, createMaskedRetryLogger as Y, resolveStateBucketWithDefaultAndSource as Yn, retryClassificationText as Yr, createSecretMasker as Yt, maskerOrIdentity as Z, stateBucketExistenceConfirmed as Zn, errorCauseChain as Zt, PRE_DELETE_SNAPSHOT_TYPES as _, escapeRegExp$1 as _n, setAwsClients as _r, isUnboundTemplateParameter as _t, DeploymentEventsStore as a, rebuildClientForBucketRegion as an, displaySafe as ar, CloudControlProvider as at, createPreDeleteFinalSnapshot as b, BOOTSTRAP_MARKER_PREFIX as bn, ConfigError as br, WAFv2WebACLProvider as bt, replayFailedOperations as c, importableOutputs as cn, canonicalizeRegion as cr, deleteIndeterminateGuards as ct, updatePartialReason as d, stringifyValue as dn, processStackMessages as dr, isTerminationProtectionPropagationError as dt, maskSecretsInText as en, CFN_TEMPLATE_URL_LIMIT as er, beginCommandInterruptScope as et, withResourceDeadline as f, WorkGraph as fn, clearBucketRegionCache as fr, IntrinsicFunctionResolver as ft, ATOMIC_FINAL_SNAPSHOT_TYPES as g, rewriteTemplateAssetReferences as gn, resetAwsClients as gr, getAccountInfo as gt, computeImplicitDeleteEdges as h, loadPublishableAssetManifest as hn, getAwsClients as hr, coerceParameterTypedValue as ht, DeploymentEventsReader as i, S3StateBackend as in, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as ir, startInterruptWatch as it, cyan as j, buildDockerImage as jn, PartialFailureError as jr, requireConfigString as jt, formatResourceLine as k, buildDenyExternalAccessPolicy as kn, MissingCdkCliError as kr, requireConfigArray as kt, replayRollback as l, shouldRetainResource as ln, derivePartitionAndUrlSuffix as lr, deleteSkipReason as lt, IMPLICIT_DELETE_DEPENDENCIES as m, createAssetRedirectResolver as mn, AwsClients as mr, cfnRefValueFromPhysicalId as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, scrubResourceRecord as nn, findLargeInlineResources as nr, interruptWatchListenerCount as nt, planFailedOps as o, exportNamesCarriedFrom as on, expectedOwnerParam as or, slowCcOperationTimeoutMs as ot, maskingRetryLogger as p, buildAssetRedirectMap as pn, resolveBucketRegion as pr, carriesDynamicReference as pt, findActionableSilentDrops as q, resolveSkipPrefix as qn, markNonRetryable as qr, STATE_SOURCED_READBACK_RULES as qt, DeployEngine as r, LockManager as rn, uploadCfnTemplate as rr, isInterruptedWaitError as rt, planRollback as s, importableOutputKeys as sn, PARTITION_TABLE as sr, UNSPECIFIED_SKIP_REASON as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, redactSecretsForState as tn, MIGRATE_TMP_PREFIX as tr, endCommandInterruptScope as tt, updatePartialMessage as u, AssetPublisher as un, AssemblyReader as ur, disableInstanceApiTermination as ut, buildFinalSnapshotIdentifier as v, stripControlChars as vn, AssetError as vr, parameterTypeMayLoseSecretIdentity as vt, makeCanonicalizePropertiesFn as w, isCrossRegionRedirect as wn, DynamicReferenceRegionAmbiguousError as wr, coerceCfnBoolean as wt, isFinalSnapshotError as x, assertAssetBucketRegion as xn, CrossAccountSecretRefusalError as xr, normalizeAwsTagsToCfn as xt, ccRoutedFinalSnapshotError as y, AssetModeResolver as yn, CdkdError as yr, refStateLookupFromResource as yt, isExportAliasCollision as z, getDockerImageBySourceHash as zn, formatError as zr, applyRoleArnIfSet as zt };
33410
+ //# sourceMappingURL=deploy-engine-DmWPwiyQ.js.map