@go-to-k/cdkd 0.284.23 → 0.284.25

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.
@@ -16860,7 +16860,7 @@ var CloudControlProvider = class {
16860
16860
  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);
16861
16861
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
16862
16862
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
16863
- const { ASGProvider } = await import("./asg-provider-Cucl2K22.js").then((n) => n.n);
16863
+ const { ASGProvider } = await import("./asg-provider-B2lPfJBN.js").then((n) => n.n);
16864
16864
  return await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
16865
16865
  }
16866
16866
  const isProtectedEc2Instance = context?.removeProtection === true && resourceType === "AWS::EC2::Instance";
@@ -17531,6 +17531,280 @@ var CloudControlProvider = class {
17531
17531
  }
17532
17532
  };
17533
17533
 
17534
+ //#endregion
17535
+ //#region src/provisioning/interrupt-watch.ts
17536
+ /**
17537
+ * The ONE interrupt watch every bounded wait under `src/provisioning/**` uses
17538
+ * (issues #2053 / #1952, consolidating the per-invocation shape PR #2033
17539
+ * introduced in `providers/custom-resource-provider.ts`).
17540
+ *
17541
+ * WHY A WAIT NEEDS ONE AT ALL
17542
+ * ---------------------------
17543
+ * `withRetry` (`src/deployment/retry.ts`) is the only wait in cdkd that
17544
+ * consults an interrupt DURING a backoff — it probes once a second while
17545
+ * sleeping. The deploy engine, `destroy-runner.ts` and `rollback-executor.ts`
17546
+ * all poll only BETWEEN operations. So a retry that threads nothing is dead to
17547
+ * Ctrl-C for its whole schedule, and on the destroy path `withResourceTimeout`
17548
+ * has by then abandoned the promise WITHOUT cancelling it, so the loop keeps
17549
+ * issuing writes behind a run the user was told had ended.
17550
+ * `docs/provider-development.md` states the requirement; `vp run
17551
+ * audit:withretry-interrupt:check` enforces it.
17552
+ *
17553
+ * WHY IT IS SHARED RATHER THAN PER MODULE
17554
+ * ---------------------------------------
17555
+ * Four modules carried a copy before issue #2104, and the copies could not
17556
+ * agree about the one thing that matters: a single `delete()` traverses more
17557
+ * than one of them, so a SIGINT marked only whichever module happened to hold a
17558
+ * live watch. One module means one latch, one error type, and ONE process
17559
+ * listener rather than four.
17560
+ *
17561
+ * FOUR PROPERTIES, EACH LOAD-BEARING
17562
+ * ----------------------------------
17563
+ *
17564
+ * 1. **The flag is per WAIT, never on a provider.** Providers are registered as
17565
+ * SINGLETONS serving concurrent resources, so provider-level state is some
17566
+ * other resource's.
17567
+ *
17568
+ * 2. **The latch is STICKY.** A watch STARTED after the signal begins is
17569
+ * already interrupted. Clearing it when the last watch is disposed — the
17570
+ * first cut — is wrong for exactly the case issue #1952 is about: a
17571
+ * `GlobalTable` delete runs the #1521 gate, then the index-busy retry loop,
17572
+ * then the gone-wait, each disposing before the next begins, so a SIGINT
17573
+ * during the gate left the two multi-minute waits after it DEAF. Only a
17574
+ * COMMAND clears it. The listener is likewise never torn down BETWEEN two
17575
+ * waits: one removed in that gap cannot record a signal landing in it, which
17576
+ * is the same bug one layer down. {@link endCommandInterruptScope} removes it
17577
+ * at command END, where there is no next wait to miss.
17578
+ *
17579
+ * 3. **It arms only inside a command that OWNS interrupt handling.** Registering
17580
+ * any SIGINT listener disables Node's default terminate, so a command with no
17581
+ * graceful shutdown of its own must not gain one here: `cdkd drift --revert`
17582
+ * reaches `provider.update` and installs nothing, and an armed watch there
17583
+ * would leave Ctrl-C setting flags nobody reads while the command carried on
17584
+ * writing to AWS — needing a SIGKILL.
17585
+ *
17586
+ * The gate is an explicit flag raised by
17587
+ * {@link beginCommandInterruptScope}, which `forwardSigtermToSigint()` calls
17588
+ * at command start. It is deliberately NOT
17589
+ * `process.listenerCount('SIGINT') > 0`, which was the first cut and is
17590
+ * defeated by the very case it was meant to catch: `cdkd drift` runs
17591
+ * `provider.update` at concurrency 4, and a concurrent CloudFront / ACM /
17592
+ * Route53 wait installs a TRANSIENT SIGINT listener of its own — so an ELBv2
17593
+ * update starting inside that window saw a non-zero count, armed, and then
17594
+ * kept the listener for the rest of the command after the transient one was
17595
+ * removed. A count answers "is anyone listening right now"; the question is
17596
+ * "does this COMMAND have a shutdown path", and only the command can say.
17597
+ * (`forwardSigtermToSigint` itself registers on SIGTERM only, so it never
17598
+ * satisfied the count either — a detail an earlier version of this comment
17599
+ * got wrong, which is how the gap survived a review.)
17600
+ *
17601
+ * Arming is re-attempted on every watch, so a wait that runs before the
17602
+ * command opens its scope does not poison later ones.
17603
+ *
17604
+ * 4. **The handler force-quits when it is the LAST listener.** Property 3 gets
17605
+ * the watch armed only under a command with a shutdown path, but that path
17606
+ * is not live for the command's whole duration: `destroy.ts` registers no
17607
+ * SIGINT handler of its own, and `destroy-runner.ts` removes its one in a
17608
+ * `finally` — so between two stacks of a multi-stack destroy the shared
17609
+ * handler is the ONLY listener. Merely latching there SWALLOWS the Ctrl-C:
17610
+ * the process does not exit, `draining` is never set, `result.interrupted`
17611
+ * stays false, and the loop proceeds to delete the NEXT stack after the user
17612
+ * asked to stop — this file's own headline failure, one layer out.
17613
+ *
17614
+ * So when no other listener remains, the handler restores exactly what Node
17615
+ * would have done with no listener at all. That is deliberately not a second
17616
+ * graceful path: inventing one would duplicate `destroy-runner.ts`'s drain
17617
+ * and have to be kept in sync with it, whereas "there is no graceful owner
17618
+ * right now, so terminate" is true by construction and needs no upkeep.
17619
+ */
17620
+ /**
17621
+ * Thrown by {@link InterruptWatch.onInterrupted}, and the ONE type the whole
17622
+ * codebase uses to mean "a wait stopped because the user asked us to stop".
17623
+ *
17624
+ * It has to be a distinct class rather than a bare `Error` because
17625
+ * `deploy-engine.ts` decides whether to ROLL BACK by asking what the failure
17626
+ * was. Its own `InterruptedError` is module-private, so a provider cannot
17627
+ * produce one; a bare `Error` from a provider therefore read as a genuine
17628
+ * resource failure and triggered an automatic rollback of the whole stack on
17629
+ * Ctrl-C — strictly worse than the unresponsiveness the threading removes.
17630
+ *
17631
+ * The explicit `setPrototypeOf` is not decoration: without it a subclass of
17632
+ * `Error` loses `instanceof` under this repo's compile target, which would make
17633
+ * {@link isInterruptedWaitError} silently answer `false`.
17634
+ */
17635
+ var InterruptedWaitError = class InterruptedWaitError extends Error {
17636
+ constructor(what) {
17637
+ super(`${what} interrupted by user (SIGINT)`);
17638
+ this.name = "InterruptedWaitError";
17639
+ Object.setPrototypeOf(this, InterruptedWaitError.prototype);
17640
+ }
17641
+ };
17642
+ /**
17643
+ * Whether `error` IS an interrupt, or WRAPS one.
17644
+ *
17645
+ * The wrap is the normal case, not the edge case: every provider catch under
17646
+ * `src/provisioning/providers/**` re-throws AWS failures as a
17647
+ * `ProvisioningError` threading the original as `cause` (issue #2040, enforced
17648
+ * by `vp run audit:provider-error-cause:check`), so by the time the engine sees
17649
+ * an interrupt it is one or more `cause` hops down. A plain `instanceof` check
17650
+ * at the engine would therefore have been a placebo.
17651
+ *
17652
+ * **The walk is bounded by a VISITED SET, not by a depth ceiling**, and the
17653
+ * difference decides correctness rather than style. A ceiling has to be sized
17654
+ * against the deepest real chain, and that chain GROWS: the flat case is 2 (the
17655
+ * provider's own wrap, then the command's), `DagExecutor` adds none — it
17656
+ * collects rather than wraps (`dag-executor.ts:178`) — but `deploy-engine.ts`
17657
+ * adds one `ProvisioningError` PER NESTED-STACK LEVEL (`deploy-engine.ts:2932`;
17658
+ * `NestedStackProvider.create` adds none of its own). A depth-5 cap therefore
17659
+ * missed at four levels of nesting, and missing here is not a degraded answer:
17660
+ * it is a full automatic rollback on Ctrl-C. The visited set gives the
17661
+ * termination the cap was really there for — a cyclic `cause` chain, which
17662
+ * would otherwise spin on the ERROR path where nothing else is watching —
17663
+ * without a ceiling any legitimate nest can cross.
17664
+ */
17665
+ function isInterruptedWaitError(error) {
17666
+ const seen = /* @__PURE__ */ new Set();
17667
+ let current = error;
17668
+ while (current !== void 0 && current !== null) {
17669
+ if (current instanceof InterruptedWaitError) return true;
17670
+ if (!(current instanceof Error)) return false;
17671
+ if (seen.has(current)) return false;
17672
+ seen.add(current);
17673
+ current = current.cause;
17674
+ }
17675
+ return false;
17676
+ }
17677
+ const liveWatches = /* @__PURE__ */ new Set();
17678
+ let sharedSigintHandler;
17679
+ let sigintLatched = false;
17680
+ /**
17681
+ * Test seam for the "this command owns interrupt handling" gate and for the
17682
+ * force-quit in property 4.
17683
+ *
17684
+ * Production never assigns either, and neither condition may be weakened to
17685
+ * accommodate tests: a command without a shutdown path really must keep Node's
17686
+ * default terminate, and a swallowed Ctrl-C in a multi-stack destroy really is
17687
+ * a blocker. `cdkd drift --revert` and `cdkd destroy` are the live instances.
17688
+ *
17689
+ * `commandOwnsInterrupts` exists because a provider suite never runs a COMMAND,
17690
+ * so every interrupt test would otherwise exercise the UNARMED path while
17691
+ * appearing to test the armed one — the worst of both, since it fails for a
17692
+ * reason unrelated to what the test claims. `forceQuit` exists because the real
17693
+ * one calls `process.exit`, which would take the test runner with it.
17694
+ */
17695
+ const interruptWatchTestSeam = {};
17696
+ /**
17697
+ * How many command scopes are currently open.
17698
+ *
17699
+ * A COUNTER rather than a boolean, because a boolean is only correct while
17700
+ * scopes never overlap. The CLI runs one command per process so they do not
17701
+ * today — but this module's own contract offers itself to "a host that runs
17702
+ * more than one command", and under a boolean the inner scope's `end` would
17703
+ * remove the shared listener and clear the OUTER command's sticky latch
17704
+ * mid-run, so a signal landing in the re-arm gap goes unrecorded. That is
17705
+ * exactly what property 2 forbids, arrived at from the other direction.
17706
+ */
17707
+ let commandInterruptScopeDepth = 0;
17708
+ function commandOwnsInterrupts() {
17709
+ const override = interruptWatchTestSeam.commandOwnsInterrupts;
17710
+ if (override !== void 0) return override();
17711
+ return commandInterruptScopeDepth > 0;
17712
+ }
17713
+ /**
17714
+ * Install the ONE process listener, if and only if the running command has
17715
+ * declared that it owns interrupt handling. See property 3 for why the "if" is
17716
+ * load-bearing rather than defensive.
17717
+ *
17718
+ * Called on every `startInterruptWatch` rather than once, so a wait that runs
17719
+ * before the command opens its interrupt scope leaves the door open instead of
17720
+ * latching a permanent "unarmed".
17721
+ */
17722
+ function armSharedSigintHandler() {
17723
+ if (sharedSigintHandler !== void 0) return;
17724
+ if (!commandOwnsInterrupts()) return;
17725
+ const handler = () => {
17726
+ sigintLatched = true;
17727
+ for (const live of liveWatches) live.interrupted = true;
17728
+ if (process.listeners("SIGINT").filter((l) => l !== handler).length === 0) {
17729
+ process.stderr.write("\nInterrupted.\nIf the next run reports a stack lock, release it with: cdkd force-unlock <stack-name>\n");
17730
+ (interruptWatchTestSeam.forceQuit ?? ((code) => process.exit(code)))(130);
17731
+ }
17732
+ };
17733
+ sharedSigintHandler = handler;
17734
+ process.on("SIGINT", handler);
17735
+ }
17736
+ /**
17737
+ * Start a watch for ONE wait. `what` names the wait in the thrown message.
17738
+ *
17739
+ * The caller MUST `dispose()` in a `finally`. A leaked watch is not merely
17740
+ * untidy: it stays in {@link liveWatches} forever, and the sticky latch means
17741
+ * every wait after a Ctrl-C would keep aborting instantly even if the run
17742
+ * somehow continued.
17743
+ */
17744
+ function startInterruptWatch(what) {
17745
+ armSharedSigintHandler();
17746
+ const state = { interrupted: sigintLatched };
17747
+ liveWatches.add(state);
17748
+ let disposed = false;
17749
+ return {
17750
+ isInterrupted: () => state.interrupted,
17751
+ onInterrupted: () => new InterruptedWaitError(what),
17752
+ dispose: () => {
17753
+ if (disposed) return;
17754
+ disposed = true;
17755
+ liveWatches.delete(state);
17756
+ }
17757
+ };
17758
+ }
17759
+ /**
17760
+ * Clear the sticky latch.
17761
+ *
17762
+ * Called by {@link beginCommandInterruptScope} and
17763
+ * {@link endCommandInterruptScope}, which bracket one command. On the CLI one
17764
+ * process runs one command, so the latch starts false regardless and those
17765
+ * calls are belt-and-braces; they earn their keep for a host that runs more
17766
+ * than one command, and for unit suites, where every test shares one process
17767
+ * and a simulated Ctrl-C would otherwise leak into every test after it.
17768
+ *
17769
+ * Deliberately NOT wired into `dispose()` — see property 2. That was the first
17770
+ * cut and it is precisely the bug: sequential waits always empty the live set
17771
+ * between them, so the latch cleared in every gap that mattered.
17772
+ */
17773
+ function resetInterruptWatchLatch() {
17774
+ sigintLatched = false;
17775
+ for (const live of liveWatches) live.interrupted = false;
17776
+ }
17777
+ /**
17778
+ * Declare that this command owns interrupt handling, and clear the latch.
17779
+ *
17780
+ * Called by `forwardSigtermToSigint()` (`src/utils/interrupt-signals.ts`),
17781
+ * which every command that reaches a provider wait through a lock invokes at
17782
+ * start — `deploy`, `destroy`, `rollback`, `state`. A command that does NOT
17783
+ * call it (`cdkd drift`) keeps Node's default terminate, which is the point.
17784
+ */
17785
+ function beginCommandInterruptScope() {
17786
+ commandInterruptScopeDepth += 1;
17787
+ if (commandInterruptScopeDepth === 1) resetInterruptWatchLatch();
17788
+ }
17789
+ /**
17790
+ * Close the scope — the command is done.
17791
+ *
17792
+ * Removing the shared listener HERE does not weaken property 2: what must never
17793
+ * happen is a teardown between two sequential WAITS, because a signal landing
17794
+ * in that gap would go unrecorded. At command end there is no next wait, and
17795
+ * leaving the listener installed would suppress default terminate for whatever
17796
+ * runs after.
17797
+ */
17798
+ function endCommandInterruptScope() {
17799
+ commandInterruptScopeDepth = Math.max(0, commandInterruptScopeDepth - 1);
17800
+ if (commandInterruptScopeDepth > 0) return;
17801
+ if (sharedSigintHandler !== void 0) {
17802
+ process.removeListener("SIGINT", sharedSigintHandler);
17803
+ sharedSigintHandler = void 0;
17804
+ }
17805
+ resetInterruptWatchLatch();
17806
+ }
17807
+
17534
17808
  //#endregion
17535
17809
  //#region src/provisioning/providers/custom-resource-provider.ts
17536
17810
  /**
@@ -17575,6 +17849,47 @@ const CR_NO_SERVICE_TOKEN_SKIP_REASON = "no ServiceToken in state — Delete han
17575
17849
  */
17576
17850
  const CR_DELETE_INVOKE_FAILED_SKIP_REASON = "Delete request to the handler did not complete — resource unproven";
17577
17851
  /**
17852
+ * Fourth sibling of the three above, for the arm where the handler RAN, was
17853
+ * reached, and answered `Status: 'FAILED'` (issue
17854
+ * [#2054](https://github.com/go-to-k/cdkd/issues/2054)).
17855
+ *
17856
+ * The terminal FAILED arm used to warn and fall through to `return undefined`,
17857
+ * which `deleteSkipReason` reads as DELETED — so cdkd dropped the state
17858
+ * record, printed the row as deleted and exited 0 over a resource the handler
17859
+ * had EXPLICITLY said it did not delete. It is the same silent-orphan class
17860
+ * {@link CR_DELETE_INVOKE_FAILED_SKIP_REASON} removed from the throw arm,
17861
+ * reached through the handler's RESPONSE instead.
17862
+ *
17863
+ * **Unconditional, with no already-gone classifier.** A handler that reports
17864
+ * FAILED because the thing it manages was already absent is a real and common
17865
+ * shape, and today's leniency lets those destroys finish green. Classifying
17866
+ * the reason to keep them green was rejected: the reason is free text a user's
17867
+ * handler writes, so any classifier is a guess, and a wrong guess
17868
+ * re-introduces exactly the orphan this arm exists to stop.
17869
+ *
17870
+ * This is therefore a COMPATIBILITY BREAK: a destroy whose delete handler
17871
+ * reports FAILED now exits 2 with the record kept, where it used to exit 0
17872
+ * with the record dropped.
17873
+ *
17874
+ * **The two callers have DIFFERENT escape hatches, and only one of them is a
17875
+ * flag.** On `cdkd deploy` the skip is forced back to exit 0 by
17876
+ * `--allow-unaddressed` (issue #1960, the flag that settled the analogous
17877
+ * exit-code question). `cdkd destroy` has no such flag — a skip raises
17878
+ * `PartialFailureError` unconditionally (`src/cli/commands/destroy.ts`) — so
17879
+ * there the remedy is the one that command's own summary names: confirm the
17880
+ * resource is gone, then drop the record with `cdkd state orphan <stack>`.
17881
+ * Messages must not offer the flag on the destroy path, which is the path this
17882
+ * arm is mostly reached from.
17883
+ *
17884
+ * **Fixed wording, no interpolation**, for the reason spelled out on
17885
+ * {@link CR_DELETE_INVOKE_FAILED_SKIP_REASON}: the handler's own `Reason` is a
17886
+ * user-authored string, it goes out on the `logger.warn` beside this, and a
17887
+ * `Reason` carrying `does not exist` / `not found` would make the deploy-side
17888
+ * replacement sites classify the skip as "already gone" and drop the record
17889
+ * one layer further out.
17890
+ */
17891
+ const CR_DELETE_HANDLER_FAILED_SKIP_REASON = "Delete handler reported FAILED — resource unproven";
17892
+ /**
17578
17893
  * The deploy-side caveat both skip warnings in this file carry (issue
17579
17894
  * [#1762](https://github.com/go-to-k/cdkd/issues/1762)).
17580
17895
  *
@@ -17585,6 +17900,29 @@ const CR_DELETE_INVOKE_FAILED_SKIP_REASON = "Delete request to the handler did n
17585
17900
  * torn down by hand. Mirrors the caveat `compositeIdFormatMessage` already
17586
17901
  * carries for the composite-id family.
17587
17902
  */
17903
+ /**
17904
+ * The bound BOTH delete-path skips in this file have to state (found in review
17905
+ * of issue [#2054](https://github.com/go-to-k/cdkd/issues/2054)).
17906
+ *
17907
+ * A skip KEEPS the state record, and the natural thing to promise is that a
17908
+ * re-run retries the handler. **On `cdkd destroy` that promise is false**, and
17909
+ * it is false in the direction that matters. `destroy-runner.ts` walks every
17910
+ * reverse-DAG level regardless of skips, so the SAME run that skipped the
17911
+ * custom resource goes on to delete its backing Lambda. The next
17912
+ * `cdkd destroy` therefore reaches the issue-#804 pre-check above, finds the
17913
+ * function gone, and treats the resource as already deleted — dropping the
17914
+ * record and exiting 0 over a resource the handler explicitly refused to
17915
+ * remove, which is the very silent orphan #2054 removed one run earlier.
17916
+ *
17917
+ * Closing it properly means making that pre-check answer `'skipped'` when the
17918
+ * teardown was never PROVEN, which needs a durable "a prior run skipped this"
17919
+ * signal. Every candidate is outside this file: a `ResourceState` field (a
17920
+ * state-schema bump), or a `DeleteContext` flag threaded from
17921
+ * `destroy-runner.ts`. So the record is described here as what it actually is
17922
+ * — a POINTER to something that has to be torn down by hand — rather than as a
17923
+ * retry that will not happen.
17924
+ */
17925
+ const CR_SKIP_NOT_A_RETRY_CAVEAT = "NOTE this record is a POINTER, not a retry: the same destroy run deletes the backing Lambda, so the next 'cdkd destroy' finds the handler gone and DROPS this record (issue 804 pre-check). Tear the resource down by hand, then clear the stack's records with 'cdkd state orphan <stack>' — that command drops EVERY record for the stack, not just this one.";
17588
17926
  const DEPLOY_SKIP_CAVEAT = "NOTE this arm is ALSO reached from cdkd deploy. Since issue 1762 the DELETE of a resource removed from the template behaves like destroy — the record is KEPT and the next deploy re-attempts it — but a REPLACEMENT / rollback delete FAILS the resource instead (https://github.com/go-to-k/cdkd/issues/1762), leaving the old one untracked; there, tear the resource down by hand.";
17589
17927
  /**
17590
17928
  * Type guard to validate Lambda response payload structure
@@ -17898,25 +18236,50 @@ const CR_LOG_TAIL_BOILERPLATE = /^(START|END|REPORT|XRAY|INIT_START|INIT_REPORT|
17898
18236
  */
17899
18237
  const SNS_SERVICE_TOKEN_ARN_RE = /^arn:aws[a-z0-9-]*:sns:/;
17900
18238
  /**
18239
+ * Account segment {@link syntheticStackId} falls back to when STS could not
18240
+ * answer (`AwsAccountInfo.fabricated`, issue
18241
+ * [#1730](https://github.com/go-to-k/cdkd/issues/1730)).
18242
+ *
18243
+ * The Cloud Control enrichment sites answer a fabricated account by OMITTING
18244
+ * the value they would have built. That is not available here — `StackId` is a
18245
+ * REQUIRED member of the custom-resource request payload — so the choice is
18246
+ * between two wrong strings, and the honest one is the one a handler cannot
18247
+ * mistake for real. `getAccountInfo`'s own fallback id (`123456789012`) is
18248
+ * shaped exactly like a live account; the all-zero id is not a valid AWS
18249
+ * account and reads as the placeholder it is.
18250
+ */
18251
+ const SYNTHETIC_STACK_ID_PLACEHOLDER_ACCOUNT = "000000000000";
18252
+ /**
17901
18253
  * The synthetic `StackId` handed to a custom-resource handler in place of the
17902
18254
  * CloudFormation stack ARN cdkd does not have.
17903
18255
  *
17904
- * **Its `arn:aws:` prefix is deliberately NOT partition-derived** (issue
17905
- * #1815, which fixed the SNS routing predicate above). Every segment of this
17906
- * value is fabricated — the region is a fixed `us-east-1` rather than the
17907
- * deploy region, and the account is the all-zero placeholder so it addresses
17908
- * nothing and cannot be made to. Deriving ONLY the partition would produce a
17909
- * strictly LESS coherent ARN (`arn:aws-cn:cloudformation:us-east-1:0000...`,
17910
- * a China partition carrying a commercial region) while fixing nothing a
17911
- * handler could rely on. The coherent fix is to synthesize the real
17912
- * partition / region / account together, which changes what every handler
17913
- * observes and belongs in its own change.
18256
+ * Partition / region / account are synthesized TOGETHER from the real deploy
18257
+ * context (issue [#1866](https://github.com/go-to-k/cdkd/issues/1866)). Every
18258
+ * segment used to be fabricated — `arn:aws:cloudformation:us-east-1:0000...`
18259
+ * regardless of where the deploy actually ranand CloudFormation-authored
18260
+ * handlers DO read `event.StackId`: to re-derive the region / account they are
18261
+ * running in, to build ARNs, to name log streams, to correlate a response.
18262
+ * Each of those read a coherent-looking ARN and got an answer that addresses
18263
+ * nothing.
18264
+ *
18265
+ * Deriving only ONE segment is worse than deriving none, which is why issue
18266
+ * #1815 deliberately left the hardcoded `arn:aws:` prefix alone rather than
18267
+ * partition-deriving it in isolation: `arn:aws-cn:cloudformation:us-east-1:…`
18268
+ * is a China partition carrying a commercial region, strictly LESS coherent
18269
+ * than a uniformly-commercial fabrication. So this takes the whole
18270
+ * {@link AwsAccountInfo} — where `partition` is already derived FROM `region`
18271
+ * — rather than any one field.
18272
+ *
18273
+ * The stack-NAME segment stays synthetic (`cdkd-<logicalId>`): cdkd has no
18274
+ * CloudFormation stack, so there is no real value to put there.
17914
18275
  *
17915
18276
  * Factored into one place so the rationale cannot go stale against two other
17916
- * copies: the create / update / delete request builders all use it.
18277
+ * copies: the create / update / delete request builders all use it, through
18278
+ * {@link CustomResourceProvider.resolveSyntheticStackId}.
17917
18279
  */
17918
- function syntheticStackId(logicalId) {
17919
- return `arn:aws:cloudformation:us-east-1:000000000000:stack/cdkd-${logicalId}/cdkd`;
18280
+ function syntheticStackId(logicalId, accountInfo) {
18281
+ const account = accountInfo.fabricated ? SYNTHETIC_STACK_ID_PLACEHOLDER_ACCOUNT : accountInfo.accountId;
18282
+ return `arn:${accountInfo.partition}:cloudformation:${accountInfo.region}:${account}:stack/cdkd-${logicalId}/cdkd`;
17920
18283
  }
17921
18284
  /**
17922
18285
  * `true` when the tail contains at least one line the HANDLER produced.
@@ -18109,11 +18472,29 @@ var CustomResourceProvider = class CustomResourceProvider {
18109
18472
  * the placeholder `PutObject`'s `withRetry` takes no knob either.
18110
18473
  */
18111
18474
  preDeliveryAuthzMaxRetries = 26;
18475
+ /**
18476
+ * The region the client bag this provider was built from was EXPLICITLY
18477
+ * configured with, or `undefined` (issue #1866).
18478
+ *
18479
+ * Captured in the constructor, beside the clients, rather than read per call:
18480
+ * `cdkd deploy` builds a region-configured `AwsClients` and a fresh
18481
+ * `ProviderRegistry` per stack, and with `--stack-concurrency` (default 4) it
18482
+ * swaps the process-global bag while other stacks are mid-flight — so a
18483
+ * call-time read can hand a SIBLING stack's region. Pairing it with the
18484
+ * clients keeps the two consistent by construction.
18485
+ *
18486
+ * `AwsClients.configuredRegion` is deliberately the only region a client bag
18487
+ * will answer (see its own note on why `client.config.region()` is unsound),
18488
+ * and `undefined` means no region was pinned anywhere — which
18489
+ * {@link getAccountInfo} then resolves from `AWS_REGION` itself.
18490
+ */
18491
+ configuredRegion;
18112
18492
  constructor(config) {
18113
18493
  const awsClients = getAwsClients();
18114
18494
  this.lambdaClient = awsClients.lambda;
18115
18495
  this.snsClient = awsClients.sns;
18116
18496
  this.s3Client = awsClients.s3;
18497
+ this.configuredRegion = awsClients.configuredRegion;
18117
18498
  this.responseBucket = config?.responseBucket;
18118
18499
  this.responsePrefix = config?.responsePrefix ?? "custom-resource-responses";
18119
18500
  this.asyncResponseTimeoutMs = config?.asyncResponseTimeoutMs ?? CustomResourceProvider.DEFAULT_ASYNC_RESPONSE_TIMEOUT_MS;
@@ -18211,6 +18592,22 @@ var CustomResourceProvider = class CustomResourceProvider {
18211
18592
  return this.responseClientResolveInFlight;
18212
18593
  }
18213
18594
  /**
18595
+ * Resolve {@link syntheticStackId} against this deploy's REAL account /
18596
+ * region / partition (issue #1866).
18597
+ *
18598
+ * `getAccountInfo` never throws — it answers a `fabricated` account when STS
18599
+ * cannot, which {@link SYNTHETIC_STACK_ID_PLACEHOLDER_ACCOUNT} handles — so
18600
+ * this cannot turn a working deploy into a failing one on the credential
18601
+ * path. It is resolved ONCE per `create` / `update` / `delete` rather than
18602
+ * per invocation attempt: the value does not vary between attempts, and the
18603
+ * request builder the retry loop re-runs is synchronous.
18604
+ */
18605
+ async resolveSyntheticStackId(logicalId) {
18606
+ const accountInfo = await getAccountInfo(this.configuredRegion);
18607
+ if (accountInfo.fabricated) this.logger.warn(`Custom resource ${logicalId}: STS did not report this deploy's account id, so the synthetic StackId handed to the handler carries the placeholder account ${SYNTHETIC_STACK_ID_PLACEHOLDER_ACCOUNT}. A handler that parses StackId to re-derive the account it is running in will not get a usable one — fix the credentials (or set AWS_ACCOUNT_ID) and re-run.`);
18608
+ return syntheticStackId(logicalId, accountInfo);
18609
+ }
18610
+ /**
18214
18611
  * Create a custom resource by invoking its Lambda handler
18215
18612
  */
18216
18613
  async create(logicalId, resourceType, properties) {
@@ -18225,7 +18622,7 @@ var CustomResourceProvider = class CustomResourceProvider {
18225
18622
  ResponseURL: invocation.responseURL,
18226
18623
  ResourceType: resourceType,
18227
18624
  LogicalResourceId: logicalId,
18228
- StackId: syntheticStackId(logicalId),
18625
+ StackId: invocation.stackId,
18229
18626
  ResourceProperties: this.stringifyProperties(properties)
18230
18627
  }));
18231
18628
  if (cfnResponse.Status === "FAILED") throw new Error(`Custom resource handler returned FAILED: ${cfnResponse.Reason || "Unknown reason"}`);
@@ -18257,7 +18654,7 @@ var CustomResourceProvider = class CustomResourceProvider {
18257
18654
  ResourceType: resourceType,
18258
18655
  LogicalResourceId: logicalId,
18259
18656
  PhysicalResourceId: physicalId,
18260
- StackId: syntheticStackId(logicalId),
18657
+ StackId: invocation.stackId,
18261
18658
  ResourceProperties: this.stringifyProperties(properties),
18262
18659
  OldResourceProperties: this.stringifyProperties(previousProperties)
18263
18660
  }));
@@ -18298,7 +18695,7 @@ var CustomResourceProvider = class CustomResourceProvider {
18298
18695
  }
18299
18696
  if (typeof serviceToken !== "string") throw new ProvisioningError(`Custom Resource ${logicalId}: ServiceToken is not a resolved string ARN (got ${typeof serviceToken}). This usually indicates state was written by a pre-fix cdkd import; re-run \`cdkd import\` or \`cdkd state orphan <stack>\` to recover.`, resourceType, logicalId, physicalId);
18300
18697
  if (!this.isSnsServiceToken(serviceToken) && await this.isBackingLambdaGone(serviceToken)) {
18301
- this.logger.warn(`Backing Lambda for custom resource ${logicalId} no longer exists (${serviceToken}); treating the custom resource as already deleted`);
18698
+ this.logger.warn(`Backing Lambda for custom resource ${logicalId} no longer exists (${serviceToken}); treating the custom resource as already deleted and DROPPING its state record. The handler can never run again, so if its teardown was never PROVEN — e.g. an earlier run reported this resource as skipped (issue 2054) — whatever it manages is still LIVE and is now untracked by cdkd. Check for leftovers before treating the stack as gone.`);
18302
18699
  return;
18303
18700
  }
18304
18701
  try {
@@ -18309,13 +18706,19 @@ var CustomResourceProvider = class CustomResourceProvider {
18309
18706
  ResourceType: resourceType,
18310
18707
  LogicalResourceId: logicalId,
18311
18708
  PhysicalResourceId: physicalId,
18312
- StackId: syntheticStackId(logicalId),
18709
+ StackId: invocation.stackId,
18313
18710
  ResourceProperties: this.stringifyProperties(properties)
18314
18711
  }));
18315
- if (cfnResponse.Status === "FAILED") this.logger.warn(`Custom resource delete handler returned FAILED for ${logicalId}: ${cfnResponse.Reason || "Unknown reason"}`);
18316
- else this.logger.debug(`Successfully deleted custom resource ${logicalId}`);
18712
+ if (cfnResponse.Status === "FAILED") {
18713
+ this.logger.warn(`Custom resource delete handler returned FAILED for ${logicalId}: ${cfnResponse.Reason || "Unknown reason"}. The handler reported that it did NOT delete, so anything this custom resource manages is LEFT IN PLACE — cdkd is KEEPING the state record and the run exits non-zero. ${CR_SKIP_NOT_A_RETRY_CAVEAT} ('cdkd deploy' also accepts --allow-unaddressed, which forces exit 0; 'cdkd destroy' has no such flag.) ${DEPLOY_SKIP_CAVEAT}`);
18714
+ return {
18715
+ outcome: "skipped",
18716
+ reason: CR_DELETE_HANDLER_FAILED_SKIP_REASON
18717
+ };
18718
+ }
18719
+ this.logger.debug(`Successfully deleted custom resource ${logicalId}`);
18317
18720
  } catch (error) {
18318
- 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 so a re-run can retry it. ${DEPLOY_SKIP_CAVEAT}`);
18721
+ 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}`);
18319
18722
  return {
18320
18723
  outcome: "skipped",
18321
18724
  reason: CR_DELETE_INVOKE_FAILED_SKIP_REASON
@@ -18391,13 +18794,22 @@ var CustomResourceProvider = class CustomResourceProvider {
18391
18794
  * PRE-delivery throw is safe to replay at all.
18392
18795
  *
18393
18796
  * `buildRequest` is called once per attempt with the fresh invocation so the
18394
- * CFn request body always carries the matching ResponseURL / RequestId.
18797
+ * CFn request body always carries the matching ResponseURL / RequestId. The
18798
+ * synthetic `StackId` rides the same bag although it is stable across
18799
+ * attempts (issue #1866), for an ORDERING reason rather than a freshness one:
18800
+ * resolving it needs an `await`, and every await before the SIGINT watch
18801
+ * below is installed is a window in which Ctrl-C is dead — `docs/
18802
+ * provider-development.md` requires a new wait site to be interruptible, and
18803
+ * the pre-delivery backoff this method owns is 47.75s long.
18804
+ *
18395
18805
  * Returns the final response; the caller decides what a terminal FAILED means
18396
- * (create/update throw, delete warns-and-continues).
18806
+ * (create / update throw; delete warns and returns `'skipped'` — issue
18807
+ * #2054, which replaced its warn-and-continue).
18397
18808
  */
18398
18809
  async invokeCustomResourceWithRetry(serviceToken, logicalId, operation, buildRequest) {
18399
- const watch = this.startInterruptWatch(logicalId);
18810
+ const watch = startInterruptWatch(`Custom resource ${logicalId}`);
18400
18811
  try {
18812
+ const stackId = await this.resolveSyntheticStackId(logicalId);
18401
18813
  let preDeliveryRetries = 0;
18402
18814
  let failedResponseRetries = 0;
18403
18815
  for (let attempt = 0;; attempt++) {
@@ -18407,7 +18819,10 @@ var CustomResourceProvider = class CustomResourceProvider {
18407
18819
  let invocation;
18408
18820
  try {
18409
18821
  invocation = await this.prepareInvocation(logicalId, watch);
18410
- const request = buildRequest(invocation);
18822
+ const request = buildRequest({
18823
+ ...invocation,
18824
+ stackId
18825
+ });
18411
18826
  this.logger.debug(`Sending custom resource ${operation.toLowerCase()} request: ${serviceToken}`);
18412
18827
  const sent = await this.sendRequest(serviceToken, request, invocation.responseKey, logicalId, operation, () => {
18413
18828
  delivered = true;
@@ -18943,33 +19358,6 @@ var CustomResourceProvider = class CustomResourceProvider {
18943
19358
  return customResourceRetryDelays.sleep(ms);
18944
19359
  }
18945
19360
  /**
18946
- * Install a SIGINT watch for one custom-resource invocation (issue #2033).
18947
- *
18948
- * `docs/provider-development.md` requires a new `withRetry` to thread
18949
- * `isInterrupted` / `onInterrupted`, and a hand-rolled backoff to be
18950
- * interruptible for the same reason: without it Ctrl-C is dead for the whole
18951
- * 47.75s schedule. The provider already had the shape — `pollS3Response`
18952
- * installs its own handler — so this is that pattern, lifted so the two new
18953
- * wait sites share one flag and one disposal.
18954
- *
18955
- * The caller MUST `dispose()` in a `finally`; a leaked listener would
18956
- * accumulate one per resource across a deploy.
18957
- */
18958
- startInterruptWatch(logicalId) {
18959
- let interrupted = false;
18960
- const handler = () => {
18961
- interrupted = true;
18962
- };
18963
- process.on("SIGINT", handler);
18964
- return {
18965
- isInterrupted: () => interrupted,
18966
- onInterrupted: () => /* @__PURE__ */ new Error(`Custom resource ${logicalId} interrupted by user`),
18967
- dispose: () => {
18968
- process.removeListener("SIGINT", handler);
18969
- }
18970
- };
18971
- }
18972
- /**
18973
19361
  * `sleep` that checks the interrupt watch at most a second apart, mirroring
18974
19362
  * `withRetry`'s own once-per-second probe. Throws the watch's error when the
18975
19363
  * user has hit Ctrl-C, so the retry loop unwinds instead of sitting out the
@@ -25385,7 +25773,7 @@ const FLUSH_INTERVAL_MS = 2e3;
25385
25773
  const FLUSH_EVENT_THRESHOLD = 50;
25386
25774
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
25387
25775
  function getCdkdVersion() {
25388
- return "0.284.23";
25776
+ return "0.284.25";
25389
25777
  }
25390
25778
  /**
25391
25779
  * Generate a time-sortable unique run id, e.g.
@@ -26829,7 +27217,7 @@ var DeployEngine = class {
26829
27217
  this.logger.warn(`Failed to save partial state before rollback: ${saveError instanceof Error ? saveError.message : String(saveError)}`);
26830
27218
  }
26831
27219
  let autoRollbackClean = false;
26832
- if (error instanceof InterruptedError) {
27220
+ if (error instanceof InterruptedError || isInterruptedWaitError(error)) {
26833
27221
  await this.writeRollbackJournalSegment(stackName, completedOperations, failedOperations, "interrupted", initialDeploy);
26834
27222
  this.logger.info(`Partial state saved (${Object.keys(newResources).length} resources). Run deploy again to resume, 'cdkd rollback' to revert, or destroy to clean up.`);
26835
27223
  throw error;
@@ -27599,7 +27987,7 @@ var DeployEngine = class {
27599
27987
  }), logicalId, 3, 5e3, deleteProvider);
27600
27988
  } catch (deleteError) {
27601
27989
  const msg = deleteError instanceof Error ? deleteError.message : String(deleteError);
27602
- if (msg.includes("does not exist") || msg.includes("was not found") || msg.includes("not found") || msg.includes("No policy found") || msg.includes("NoSuchEntity") || msg.includes("NotFoundException") || msg.includes("ResourceNotFoundException")) this.logger.debug(`Resource ${logicalId} already deleted (${msg}), removing from state`);
27990
+ if (!isInterruptedWaitError(deleteError) && (msg.includes("does not exist") || msg.includes("was not found") || msg.includes("not found") || msg.includes("No policy found") || msg.includes("NoSuchEntity") || msg.includes("NotFoundException") || msg.includes("ResourceNotFoundException"))) this.logger.debug(`Resource ${logicalId} already deleted (${msg}), removing from state`);
27603
27991
  else throw deleteError;
27604
27992
  }
27605
27993
  const deleteSkipped = deleteSkipReason(deleteResult);
@@ -28005,5 +28393,5 @@ var DeployEngine = class {
28005
28393
  };
28006
28394
 
28007
28395
  //#endregion
28008
- export { disableInstanceApiTermination as $, NestedStackChildDirectDestroyError as $n, ensureAssetStorage as $t, isStatefulRecreateTargetSync as A, uploadCfnTemplate as An, s3BucketWebsiteUrl as At, collectPublishedOutputNames as B, getAwsClients as Bn, rebuildClientForBucketRegion as Bt, createPreDeleteFinalSnapshot as C, resolveUseCdkBootstrapAssets as Cn, maskSecretsInText as Ct, makeCanonicalizePropertiesFn as D, CFN_TEMPLATE_URL_LIMIT as Dn, s3BucketDomainName as Dt, unsupportedFinalSnapshotError as E, CFN_TEMPLATE_BODY_LIMIT as En, s3BucketArn as Et, gray as F, AssemblyReader as Fn, withRetry as Ft, IAMRoleProvider as G, ConfigError as Gn, buildAssetRedirectMap as Gt, isExportAliasCollision as H, setAwsClients as Hn, AssetPublisher as Ht, green as I, processStackMessages as In, DagBuilder as It, ProviderRegistry as J, LocalInvokeBuildError as Jn, rewriteTemplateAssetReferences as Jt, collectInlinePolicyNamesManagedBySiblings as K, DependencyError as Kn, createAssetRedirectResolver as Kt, red as L, clearBucketRegionCache as Ln, TemplateParser as Lt, formatResourceLine as M, PARTITION_TABLE as Mn, DiffCalculator as Mt, bold as N, canonicalizeRegion as Nn, INTRINSIC_KEYS as Nt, extractDeploymentEventError as O, MIGRATE_TMP_PREFIX as On, s3BucketDualStackDomainName as Ot, cyan as P, derivePartitionAndUrlSuffix as Pn, describeTypeWithThrottleRetry as Pt, slowCcOperationTimeoutMs as Q, MissingCdkCliError as Qn, BOOTSTRAP_MARKER_PREFIX as Qt, yellow as R, resolveBucketRegion as Rn, LockManager as Rt, ccRoutedFinalSnapshotError as S, resolveStateBucketWithDefaultAndSource as Sn, isSingleDynamicReferenceToken as St, refusesFinalSnapshot as T, warnDeprecatedNoPrefixCliFlag as Tn, scrubResourceRecord as Tt, secretBearingStateKeyWarning as U, AssetError as Un, stringifyValue as Ut, exportAliasCollisionScrubWarning as V, resetAwsClients as Vn, shouldRetainResource as Vt, stateKeySecretExposure as W, CdkdError as Wn, WorkGraph as Wt, findSilentDropProperties as X, LocalStartServiceError as Xn, stripControlChars as Xt, findActionableSilentDrops as Y, LocalMigrateError as Yn, escapeRegExp$1 as Yt, CloudControlProvider as Z, LockError as Zn, AssetModeResolver as Zt, IMPLICIT_DELETE_DEPENDENCIES as _, resolveApp as _n, STATE_SOURCED_CROSS_GENERATION_RULES as _t, DeploymentEventsStore as a, buildDenyExternalAccessPolicy as an, StackTerminationProtectionError as ar, WAFv2WebACLProvider as at, PRE_DELETE_SNAPSHOT_TYPES as b, resolveSkipPrefix as bn, createSecretMasker as bt, producerRegionsFromState as c, getDockerCmd as cn, formatError as cr, assertRegionMatch as ct, updatePartialMessage as d, AssetManifestLoader as dn, withErrorHandling as dr, configStringRefusal as dt, getBootstrapMarkerKey as en, PartialFailureError as er, isTerminationProtectionPropagationError as et, updatePartialReason as f, getDockerImageBySourceHash as fn, isMarkedNonRetryable as fr, readConfigString as ft, maskingRetryLogger as g, getLegacyStateBucketName as gn, __exportAll as gr, requireConfigString as gt, withResourceDeadline as h, getDefaultStateBucketName as hn, markNonRetryable as hr, requireConfigObject as ht, DeploymentEventsReader as i, validateContainerRepoName as in, StackHasActiveImportsError as ir, refStateLookupFromResource as it, renderStatefulReason as j, expectedOwnerParam as jn, applyRoleArnIfSet as jt, MULTI_REGION_RECREATE_BLOCKED_TYPES as k, findLargeInlineResources as kn, s3BucketRegionalDomainName as kt, replayFailedOperations as l, runDockerForeground as ln, isCdkdError as lr, coerceCfnBoolean as lt, deleteSkipReason as m, synthesisStatusMessage as mn, isThrottlingError as mr, requireConfigArray as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, readBootstrapMarkerBody as nn, ResourceTimeoutError as nr, cfnRefValueFromPhysicalId as nt, planFailedOps as o, buildDockerImage as on, StateError as or, normalizeAwsTagsToCfn as ot, UNSPECIFIED_SKIP_REASON as p, Synthesizer as pn, isRetryableTransientError as pr, replayWarn as pt, clearOnUpdateRemoval as q, DeployCancelledError as qn, loadPublishableAssetManifest as qt, DeployEngine as r, validateAssetBucketName as rn, ResourceUpdateNotSupportedError as rr, getAccountInfo as rt, planRollback as s, formatDockerLoginError as sn, SynthesisError as sr, resolveExplicitPhysicalId as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, parseBootstrapMarker as tn, ProvisioningError as tr, IntrinsicFunctionResolver as tt, replayRollback as u, runDockerStreaming as un, normalizeAwsError as ur, configBooleanRefusal as ut, computeImplicitDeleteEdges as v, resolveAutoAssetStorage as vn, STATE_SOURCED_READBACK_RULES as vt, isFinalSnapshotError as w, stateBucketExistenceConfirmed as wn, redactSecretsForState as wt, buildFinalSnapshotIdentifier as x, resolveStateBucketWithDefault as xn, dynamicReferenceTokens as xt, ATOMIC_FINAL_SNAPSHOT_TYPES as y, resolveCaptureObservedState as yn, TEMPLATE_SOURCED_RULES as yt, collectDeclaredOutputNames as z, AwsClients as zn, S3StateBackend as zt };
28009
- //# sourceMappingURL=deploy-engine-HfFU96oJ.js.map
28396
+ export { isInterruptedWaitError as $, LocalMigrateError as $n, escapeRegExp$1 as $t, isStatefulRecreateTargetSync as A, CFN_TEMPLATE_BODY_LIMIT as An, s3BucketArn as At, collectPublishedOutputNames as B, processStackMessages as Bn, DagBuilder as Bt, createPreDeleteFinalSnapshot as C, resolveCaptureObservedState as Cn, TEMPLATE_SOURCED_RULES as Ct, makeCanonicalizePropertiesFn as D, resolveUseCdkBootstrapAssets as Dn, maskSecretsInText as Dt, unsupportedFinalSnapshotError as E, resolveStateBucketWithDefaultAndSource as En, isSingleDynamicReferenceToken as Et, gray as F, expectedOwnerParam as Fn, applyRoleArnIfSet as Ft, IAMRoleProvider as G, resetAwsClients as Gn, shouldRetainResource as Gt, isExportAliasCollision as H, resolveBucketRegion as Hn, LockManager as Ht, green as I, PARTITION_TABLE as In, DiffCalculator as It, ProviderRegistry as J, CdkdError as Jn, WorkGraph as Jt, collectInlinePolicyNamesManagedBySiblings as K, setAwsClients as Kn, AssetPublisher as Kt, red as L, canonicalizeRegion as Ln, INTRINSIC_KEYS as Lt, formatResourceLine as M, MIGRATE_TMP_PREFIX as Mn, s3BucketDualStackDomainName as Mt, bold as N, findLargeInlineResources as Nn, s3BucketRegionalDomainName as Nt, extractDeploymentEventError as O, stateBucketExistenceConfirmed as On, redactSecretsForState as Ot, cyan as P, uploadCfnTemplate as Pn, s3BucketWebsiteUrl as Pt, endCommandInterruptScope as Q, LocalInvokeBuildError as Qn, rewriteTemplateAssetReferences as Qt, yellow as R, derivePartitionAndUrlSuffix as Rn, describeTypeWithThrottleRetry as Rt, ccRoutedFinalSnapshotError as S, resolveAutoAssetStorage as Sn, STATE_SOURCED_READBACK_RULES as St, refusesFinalSnapshot as T, resolveStateBucketWithDefault as Tn, dynamicReferenceTokens as Tt, secretBearingStateKeyWarning as U, AwsClients as Un, S3StateBackend as Ut, exportAliasCollisionScrubWarning as V, clearBucketRegionCache as Vn, TemplateParser as Vt, stateKeySecretExposure as W, getAwsClients as Wn, rebuildClientForBucketRegion as Wt, findSilentDropProperties as X, DependencyError as Xn, createAssetRedirectResolver as Xt, findActionableSilentDrops as Y, ConfigError as Yn, buildAssetRedirectMap as Yt, beginCommandInterruptScope as Z, DeployCancelledError as Zn, loadPublishableAssetManifest as Zt, IMPLICIT_DELETE_DEPENDENCIES as _, Synthesizer as _n, isRetryableTransientError as _r, replayWarn as _t, DeploymentEventsStore as a, parseBootstrapMarker as an, ProvisioningError as ar, IntrinsicFunctionResolver as at, PRE_DELETE_SNAPSHOT_TYPES as b, getLegacyStateBucketName as bn, __exportAll as br, requireConfigString as bt, producerRegionsFromState as c, validateContainerRepoName as cn, StackHasActiveImportsError as cr, refStateLookupFromResource as ct, updatePartialMessage as d, formatDockerLoginError as dn, SynthesisError as dr, resolveExplicitPhysicalId as dt, stripControlChars as en, LocalStartServiceError as er, startInterruptWatch as et, updatePartialReason as f, getDockerCmd as fn, formatError as fr, assertRegionMatch as ft, maskingRetryLogger as g, getDockerImageBySourceHash as gn, isMarkedNonRetryable as gr, readConfigString as gt, withResourceDeadline as h, AssetManifestLoader as hn, withErrorHandling as hr, configStringRefusal as ht, DeploymentEventsReader as i, getBootstrapMarkerKey as in, PartialFailureError as ir, isTerminationProtectionPropagationError as it, renderStatefulReason as j, CFN_TEMPLATE_URL_LIMIT as jn, s3BucketDomainName as jt, MULTI_REGION_RECREATE_BLOCKED_TYPES as k, warnDeprecatedNoPrefixCliFlag as kn, scrubResourceRecord as kt, replayFailedOperations as l, buildDenyExternalAccessPolicy as ln, StackTerminationProtectionError as lr, WAFv2WebACLProvider as lt, deleteSkipReason as m, runDockerStreaming as mn, normalizeAwsError as mr, configBooleanRefusal as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, BOOTSTRAP_MARKER_PREFIX as nn, MissingCdkCliError as nr, slowCcOperationTimeoutMs as nt, planFailedOps as o, readBootstrapMarkerBody as on, ResourceTimeoutError as or, cfnRefValueFromPhysicalId as ot, UNSPECIFIED_SKIP_REASON as p, runDockerForeground as pn, isCdkdError as pr, coerceCfnBoolean as pt, clearOnUpdateRemoval as q, AssetError as qn, stringifyValue as qt, DeployEngine as r, ensureAssetStorage as rn, NestedStackChildDirectDestroyError as rr, disableInstanceApiTermination as rt, planRollback as s, validateAssetBucketName as sn, ResourceUpdateNotSupportedError as sr, getAccountInfo as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, AssetModeResolver as tn, LockError as tr, CloudControlProvider as tt, replayRollback as u, buildDockerImage as un, StateError as ur, normalizeAwsTagsToCfn as ut, computeImplicitDeleteEdges as v, synthesisStatusMessage as vn, isThrottlingError as vr, requireConfigArray as vt, isFinalSnapshotError as w, resolveSkipPrefix as wn, createSecretMasker as wt, buildFinalSnapshotIdentifier as x, resolveApp as xn, STATE_SOURCED_CROSS_GENERATION_RULES as xt, ATOMIC_FINAL_SNAPSHOT_TYPES as y, getDefaultStateBucketName as yn, markNonRetryable as yr, requireConfigObject as yt, collectDeclaredOutputNames as z, AssemblyReader as zn, withRetry as zt };
28397
+ //# sourceMappingURL=deploy-engine-BpZWPiaL.js.map