@go-to-k/cdkd 0.294.10 → 0.294.12

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.
@@ -2,7 +2,7 @@ import { r as getAwsClients, s as __exportAll } from "./aws-clients-CnmtbrxD.js"
2
2
  import { A as displaySafe, E as UNRENDERABLE, F as safeMsg, L as truncateCodePoints, M as isPasteableIdent, O as displayAwsMessage, P as plainIdentOr, S as withoutGeneratedFallbackName, T as STACK_REF_MAX_CODE_POINTS, _ as getCurrentSkipPrefix, b as withSkipPrefix, c as getLiveRenderer, f as applyDefaultNameForFallback, g as generateResourceNameWithFallback, h as generateResourceName, j as displayStackName, k as displayIdent, m as explicitNamePropertyFor, n as getLogger, r as isStdoutReservedForPayload, s as installLogLineMaskerSource, v as getCurrentStackName, w as SECRET_REF_MAX_CODE_POINTS, x as withStackName, y as looksLikeCdkdGeneratedName } from "./logger-B46YMG0h.js";
3
3
  import { $t as StateError, A as isTerminalDeleteFailure, An as isAmbiguousCcHandlerErrorCode, At as clientDefaultsFor, Bn as isMarkedNonRetryable, Bt as IntrinsicResolutionRefusalError, C as refusalTypeShown, Cn as isNameCollisionErrorFrom, D as ProtectionFlipRegistry, Dt as withPasteableAwsProfile, En as isReplayedNameCollisionFrom, Fn as retryClassificationText, Gt as MalformedProducerRecordRefusalError, H as pasteableAwsCommand, Hn as markNonRetryable, In as describeAwsFailure, It as CrossAccountSecretRefusalError, J as isInterruptedWaitError, Jt as ProvisioningError, Lt as DependencyError, M as observeThenDisableProtection, Mn as isIamPropagationError, Mt as AccountIdUnavailableError, N as protectionFlipKey, Nn as isRetryableTransientError, Nt as AssetError, O as compensateProtectionFlip, On as markReplayMayCollide, Ot as ambientClientDefaults, Pn as isTransientServerError, Pt as CdkdError, Q as canonicalizeRoute53QueryName, R as DELETION_PROTECTION_DOC_POINTER, Rn as safeStringify$1, S as quotedRemedyLogicalId, Sn as hasReplayMayCollide, St as injectiveKey, T as resolveExplicitPhysicalId, Tn as isRecreateRetryableError, Tt as producerRecordKey, U as protectedReplacementAdvice, Un as markRedactedCause, Ut as LockError, Vn as isThrottlingError, Wn as wrapMaskedAwsError, Wt as MacroExpansionError, X as ElapsedBudgetRegistry, Xt as ResourceUpdateNotSupportedError, Y as startInterruptWatch, Yt as ResourceTimeoutError, Z as monotonicNowMs, _n as shellQuote, _t as formatLockOperation, at as segmentAfterAnchor, b as isQuotableImportValue, bt as CUSTOM_RESOURCE_RESPONSE_PREFIX, cn as UNSHOWABLE_VALUE, ct as isSecretDerivedValue, d as prepareRemovalForUpdate, dn as isInertUnquoted, dt as withDerivedNameMasks, en as SynthesisError, et as compositeIdSeparatorRefusal, f as removalWarning, fn as pasteableCommand, ft as UNREPRODUCIBLE_LOCK_CLAUSE, g as assertRegionMatch, gn as shellBoundedDisplay, gt as formatLockExpiry, h as RESOURCE_NOT_FOUND, hn as quotedOrDescribed, i as holdsSecretDerivedEntry, it as resourceTypeShown, jn as isAmbiguousOutcomeError, jt as credentialFingerprint, k as deleteWithProtectionCompensation, kn as formatRetryClassificationSignals, kt as ambientCredentialConfig, l as withUnchangedSecretPrincipalLists, ln as commandHole, lt as maskDeep, m as withoutInjectedRemovals, mn as plainOrDescribed, nt as logicalIdShown, on as SHELL_ACTIVE, ot as createMaskedLogSinks, pn as physicalIdShownBesideCommand, pt as buildForceUnlockCommand, rn as normalizeAwsError, sn as SHELL_ACTIVE_WHY, st as createMaskedRetryLogger, ut as maskerOrIdentity, vn as withheldTargetClause, vt as formatLockOwner, wn as isNameCooldownError, x as normalizeAwsTagsToCfn, xn as isUpdateUnsupportedError, xt as DEFAULT_STATE_PREFIX, yt as sanitizeRecoveryValue, zt as DynamicReferenceRegionAmbiguousError } from "./iam-policy-targets-CMSQGQnm.js";
4
4
  import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, s as ambientRegion, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-D0q0z4dG.js";
5
- import { t as getCdkdVersion } from "./version-BNo3JdVW.js";
5
+ import { t as getCdkdVersion } from "./version-D_N3IrrJ.js";
6
6
  import { createHash, randomUUID } from "node:crypto";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
8
8
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -4683,6 +4683,41 @@ function orphansAfterRollback(previous, newlyOrphaned) {
4683
4683
  //#endregion
4684
4684
  //#region src/types/rollback-journal.ts
4685
4685
  const ROLLBACK_JOURNAL_VERSION = 1;
4686
+ function splitImportedOps(ops, segment, except = /* @__PURE__ */ new Set()) {
4687
+ const marks = segment.importedResources ?? [];
4688
+ const replay = [];
4689
+ const imported = [];
4690
+ const displaced = [];
4691
+ for (const op of ops) {
4692
+ const ofId = except.has(op.logicalId) ? [] : marks.filter((m) => m.logicalId === op.logicalId);
4693
+ if (ofId.length === 0) replay.push(op);
4694
+ else if (ofId.some((m) => isMarkFor(m, op)) && retainedOldPhysicalId(op) === void 0) imported.push(op);
4695
+ else displaced.push(op);
4696
+ }
4697
+ return {
4698
+ replay,
4699
+ imported,
4700
+ displaced
4701
+ };
4702
+ }
4703
+ function journalOpPhysicalId(op) {
4704
+ if (op.physicalId !== void 0) return op.physicalId;
4705
+ const prev = op.previousState?.physicalId;
4706
+ return op.changeType === "DELETE" && typeof prev === "string" && prev !== "" ? prev : void 0;
4707
+ }
4708
+ function retainedOldPhysicalId(op) {
4709
+ if (op.changeType !== "UPDATE") return void 0;
4710
+ const prev = op.previousState?.physicalId;
4711
+ if (typeof prev !== "string" || prev === "") return void 0;
4712
+ const prevType = op.previousState?.resourceType;
4713
+ const oldType = op.previousResourceType ?? (typeof prevType === "string" && prevType !== "" ? prevType : void 0);
4714
+ if (!(prev !== journalOpPhysicalId(op) || oldType !== void 0 && oldType !== op.resourceType)) return void 0;
4715
+ return op.oldResourceRetained !== false ? prev : void 0;
4716
+ }
4717
+ function isMarkFor(mark, op) {
4718
+ const own = journalOpPhysicalId(op);
4719
+ return own !== void 0 && mark.logicalId === op.logicalId && mark.physicalId === own && mark.resourceType === op.resourceType;
4720
+ }
4686
4721
  var UnknownRollbackJournalVersionError = class extends Error {
4687
4722
  foundVersion;
4688
4723
  stackName;
@@ -4753,6 +4788,7 @@ function parseRollbackJournal(bodyString, stackName) {
4753
4788
  seg["failedOperations"].forEach((op, i) => refuseMalformedOperation(shownStack, `segments[${s}].failedOperations[${i}]`, op));
4754
4789
  }
4755
4790
  if (seg["supersededLogicalIds"] !== void 0 && (!Array.isArray(seg["supersededLogicalIds"]) || !seg["supersededLogicalIds"].every((id) => typeof id === "string"))) refuseMalformed(shownStack, `segments[${s}].supersededLogicalIds must be an array of strings when present.`);
4791
+ if (seg["importedResources"] !== void 0 && (!Array.isArray(seg["importedResources"]) || !seg["importedResources"].every((m) => typeof m === "object" && m !== null && typeof m["logicalId"] === "string" && typeof m["physicalId"] === "string" && typeof m["resourceType"] === "string"))) refuseMalformed(shownStack, `segments[${s}].importedResources must be an array of { logicalId, physicalId, resourceType } strings when present.`);
4756
4792
  if (seg["runId"] !== void 0 && typeof seg["runId"] !== "string") refuseMalformed(shownStack, `segments[${s}].runId must be a string when present (got ${kind(seg["runId"])}).`);
4757
4793
  if (seg["skipPrefix"] !== void 0 && typeof seg["skipPrefix"] !== "boolean") refuseMalformed(shownStack, `segments[${s}].skipPrefix must be a boolean when present (got ${kind(seg["skipPrefix"])}).`);
4758
4794
  const reads = seg["previousCrossStackReads"];
@@ -5370,6 +5406,23 @@ var S3StateBackend = class {
5370
5406
  addSupersededIds(newest, logicalIds);
5371
5407
  await this.putRawObject(this.getRollbackJournalKey(stackName, region), JSON.stringify(journal, null, 2));
5372
5408
  }
5409
+ async markRollbackJournalImported(stackName, region, marks) {
5410
+ if (marks.length === 0) return [];
5411
+ const journal = await this.loadRollbackJournal(stackName, region);
5412
+ if (!journal) return [];
5413
+ const marked = /* @__PURE__ */ new Set();
5414
+ for (const segment of journal.segments) {
5415
+ const named = new Set([...segment.operations, ...segment.failedOperations ?? []].map((op) => op.logicalId));
5416
+ const hits = marks.filter((m) => named.has(m.logicalId));
5417
+ if (hits.length === 0) continue;
5418
+ segment.importedResources = [...(segment.importedResources ?? []).filter((k) => !hits.some((m) => m.logicalId === k.logicalId)), ...hits.map((m) => ({ ...m }))];
5419
+ for (const m of hits) marked.add(m.logicalId);
5420
+ }
5421
+ if (marked.size === 0) return [];
5422
+ addSupersededIds(journal.segments[journal.segments.length - 1], [...marked]);
5423
+ await this.putRawObject(this.getRollbackJournalKey(stackName, region), JSON.stringify(journal, null, 2));
5424
+ return [...marked];
5425
+ }
5373
5426
  async dropRollbackJournalSegments(stackName, region, drop) {
5374
5427
  const journal = await this.loadRollbackJournal(stackName, region);
5375
5428
  if (!journal) return 0;
@@ -6077,7 +6130,7 @@ const WHOLE_DYNAMIC_REFERENCE_PATTERN = new RegExp(`^\\{\\{resolve:${DYNAMIC_REF
6077
6130
  function isSingleDynamicReferenceToken(value) {
6078
6131
  return WHOLE_DYNAMIC_REFERENCE_PATTERN.test(value);
6079
6132
  }
6080
- function isPlainObject$3(value) {
6133
+ function isPlainObject$4(value) {
6081
6134
  return value !== null && typeof value === "object" && !Array.isArray(value);
6082
6135
  }
6083
6136
 
@@ -6262,7 +6315,7 @@ function crossStackSourceKey(source) {
6262
6315
  }
6263
6316
  if (key === "Fn::GetStackOutput") {
6264
6317
  const args = source[key];
6265
- if (!isPlainObject$3(args)) return void 0;
6318
+ if (!isPlainObject$4(args)) return void 0;
6266
6319
  const stackName = Object.hasOwn(args, "StackName") ? literalStringOrUndefined(args["StackName"]) : void 0;
6267
6320
  const outputName = Object.hasOwn(args, "OutputName") ? literalStringOrUndefined(args["OutputName"]) : void 0;
6268
6321
  if (stackName === void 0 || outputName === void 0) return void 0;
@@ -6308,7 +6361,7 @@ function crossStackSourceKey(source) {
6308
6361
  let template;
6309
6362
  let variables;
6310
6363
  if (typeof raw === "string") template = raw;
6311
- else if (Array.isArray(raw) && raw.length === 2 && isPlainObject$3(raw[1])) {
6364
+ else if (Array.isArray(raw) && raw.length === 2 && isPlainObject$4(raw[1])) {
6312
6365
  if (typeof raw[0] !== "string") return void 0;
6313
6366
  template = raw[0];
6314
6367
  variables = raw[1];
@@ -6408,7 +6461,7 @@ function appendValuePlaceholderParts(value, out, budget, depth) {
6408
6461
  if (budget.exhausted) return;
6409
6462
  const literal = joinPartLiteralText(value);
6410
6463
  if (literal !== void 0) return pushPlaceholderPart(out, literal, budget);
6411
- if (isPlainObject$3(value) && Object.keys(value).length === 1) {
6464
+ if (isPlainObject$4(value) && Object.keys(value).length === 1) {
6412
6465
  const ref = value["Ref"];
6413
6466
  if (typeof ref === "string" && ref !== "") return pushPlaceholderPart(out, keyedPart({ Ref: ref }), budget);
6414
6467
  if (depth >= MAX_PLACEHOLDER_DEPTH) {
@@ -6440,7 +6493,7 @@ function appendParameterPlaceholderParts(source, out, budget, depth) {
6440
6493
  let template;
6441
6494
  let variables = {};
6442
6495
  if (typeof args === "string") template = args;
6443
- else if (Array.isArray(args) && args.length === 2 && isPlainObject$3(args[1])) {
6496
+ else if (Array.isArray(args) && args.length === 2 && isPlainObject$4(args[1])) {
6444
6497
  template = args[0];
6445
6498
  variables = args[1];
6446
6499
  } else return false;
@@ -6583,7 +6636,7 @@ function isUniquelyKeyedBy(items, key) {
6583
6636
  if (items.length === 0) return false;
6584
6637
  const seen = /* @__PURE__ */ new Set();
6585
6638
  for (const item of items) {
6586
- if (!isPlainObject$3(item) || !Object.hasOwn(item, key)) return false;
6639
+ if (!isPlainObject$4(item) || !Object.hasOwn(item, key)) return false;
6587
6640
  const id = item[key];
6588
6641
  if (typeof id !== "string" || id === "") return false;
6589
6642
  if (seen.has(id)) return false;
@@ -6613,7 +6666,7 @@ function redactByPath(bag, source, secrets, rules, secretExpressions, bagIsSameG
6613
6666
  }
6614
6667
  return positionByEmbeddedSpan(bag, source, secrets, bagIsSameGeneration);
6615
6668
  }
6616
- if (typeof bag === "string" && isPlainObject$3(source)) {
6669
+ if (typeof bag === "string" && isPlainObject$4(source)) {
6617
6670
  const certified = positionByCrossStackSource(bag, source, secrets);
6618
6671
  if (certified !== void 0) return certified;
6619
6672
  const placeheld = positionByParameterPlaceholders(bag, source, secrets);
@@ -6623,7 +6676,7 @@ function redactByPath(bag, source, secrets, rules, secretExpressions, bagIsSameG
6623
6676
  const framed = positionByIntrinsicFrame(bag, source, secrets, secretExpressions, bagIsSameGeneration);
6624
6677
  if (framed !== void 0) return framed;
6625
6678
  }
6626
- if (Array.isArray(bag) && isPlainObject$3(source)) {
6679
+ if (Array.isArray(bag) && isPlainObject$4(source)) {
6627
6680
  const positionedList = positionListByCrossStackSource(bag, source, secrets);
6628
6681
  if (positionedList !== void 0) return positionedList;
6629
6682
  }
@@ -6651,7 +6704,7 @@ function redactByPath(bag, source, secrets, rules, secretExpressions, bagIsSameG
6651
6704
  }
6652
6705
  if (rules.descendArrays && bag.length === source.length) return bag.map((item, i) => redactByPath(item, source[i], secrets, rules, secretExpressions, bagIsSameGeneration));
6653
6706
  }
6654
- if (isPlainObject$3(bag) && hasPlainPrototype(bag) && isPlainObject$3(source)) {
6707
+ if (isPlainObject$4(bag) && hasPlainPrototype(bag) && isPlainObject$4(source)) {
6655
6708
  const out = Object.create(null);
6656
6709
  for (const [k, v] of Object.entries(bag)) out[k] = Object.hasOwn(source, k) ? redactByPath(v, source[k], secrets, rules, secretExpressions, bagIsSameGeneration) : redactSecretsForState(v, secrets);
6657
6710
  return out;
@@ -6664,7 +6717,7 @@ function isReadbackProjectedFromState(rules) {
6664
6717
  function subtreeHasDynamicReference(value) {
6665
6718
  if (isDynamicReferenceString(value)) return true;
6666
6719
  if (Array.isArray(value)) return value.some(subtreeHasDynamicReference);
6667
- if (isPlainObject$3(value)) return Object.values(value).some(subtreeHasDynamicReference);
6720
+ if (isPlainObject$4(value)) return Object.values(value).some(subtreeHasDynamicReference);
6668
6721
  return false;
6669
6722
  }
6670
6723
  function pathCrossesDottedKey(bag, path) {
@@ -6726,8 +6779,8 @@ function deepEqualJsonValue(a, b) {
6726
6779
  if (!Array.isArray(b) || a.length !== b.length) return false;
6727
6780
  return a.every((item, i) => deepEqualJsonValue(item, b[i]));
6728
6781
  }
6729
- if (isPlainObject$3(a)) {
6730
- if (!isPlainObject$3(b)) return false;
6782
+ if (isPlainObject$4(a)) {
6783
+ if (!isPlainObject$4(b)) return false;
6731
6784
  if (!hasPlainPrototype(a) || !hasPlainPrototype(b)) return false;
6732
6785
  const keys = Object.keys(a);
6733
6786
  if (keys.length !== Object.keys(b).length) return false;
@@ -6753,7 +6806,7 @@ function refuseUncertifiedSubtree(value, sourceLiterals, mark, seen = /* @__PURE
6753
6806
  for (const item of value) out.push(refuseUncertifiedSubtree(item, sourceLiterals, mark, seen));
6754
6807
  return out;
6755
6808
  }
6756
- if (isPlainObject$3(value) && hasPlainPrototype(value)) {
6809
+ if (isPlainObject$4(value) && hasPlainPrototype(value)) {
6757
6810
  const out = Object.create(null);
6758
6811
  seen.set(value, out);
6759
6812
  for (const [k, v] of Object.entries(value)) out[k] = refuseUncertifiedSubtree(v, sourceLiterals, mark, seen);
@@ -6781,7 +6834,7 @@ function refuseUncertifiedReadbackPositions(bag, source, secrets, failClosed, le
6781
6834
  return mark ? POSITION_DECIDED : source;
6782
6835
  }
6783
6836
  if (!subtreeHasDynamicReference(source)) return bag;
6784
- if (isPlainObject$3(bag) && hasPlainPrototype(bag) && isPlainObject$3(source)) {
6837
+ if (isPlainObject$4(bag) && hasPlainPrototype(bag) && isPlainObject$4(source)) {
6785
6838
  const out = Object.create(null);
6786
6839
  for (const [k, v] of Object.entries(bag)) out[k] = Object.hasOwn(source, k) ? refuseUncertifiedReadbackPositions(v, source[k], secrets, failClosed, learn, mark) : v;
6787
6840
  return out;
@@ -6808,14 +6861,14 @@ function refuseUncertifiedReadbackPositions(bag, source, secrets, failClosed, le
6808
6861
  function isDistinguishingAnchor(value) {
6809
6862
  if (typeof value === "string") return value !== "";
6810
6863
  if (Array.isArray(value)) return value.some(isDistinguishingAnchor);
6811
- if (isPlainObject$3(value)) return Object.values(value).some(isDistinguishingAnchor);
6864
+ if (isPlainObject$4(value)) return Object.values(value).some(isDistinguishingAnchor);
6812
6865
  return false;
6813
6866
  }
6814
6867
  const ANCHOR_REFERENCE_MASK = "<ref>";
6815
6868
  function anchorSignature(source) {
6816
6869
  if (isDynamicReferenceString(source)) return ANCHOR_REFERENCE_MASK;
6817
6870
  if (Array.isArray(source)) return `[${source.map(anchorSignature).sort().join(",")}]`;
6818
- if (isPlainObject$3(source)) return `{${Object.keys(source).sort().map((k) => `${JSON.stringify(k)}:${anchorSignature(source[k])}`).join(",")}}`;
6871
+ if (isPlainObject$4(source)) return `{${Object.keys(source).sort().map((k) => `${JSON.stringify(k)}:${anchorSignature(source[k])}`).join(",")}}`;
6819
6872
  return JSON.stringify(source) ?? "undefined";
6820
6873
  }
6821
6874
  function anchorsCorroboratePairing(bag, source, anchors) {
@@ -6825,8 +6878,8 @@ function anchorsCorroboratePairing(bag, source, anchors) {
6825
6878
  return true;
6826
6879
  }
6827
6880
  if (isDynamicReferenceString(source)) return typeof bag === "string";
6828
- if (isPlainObject$3(source)) {
6829
- if (!isPlainObject$3(bag)) return false;
6881
+ if (isPlainObject$4(source)) {
6882
+ if (!isPlainObject$4(bag)) return false;
6830
6883
  return Object.keys(source).every((k) => Object.hasOwn(bag, k) && anchorsCorroboratePairing(bag[k], source[k], anchors));
6831
6884
  }
6832
6885
  if (Array.isArray(source)) {
@@ -6917,13 +6970,13 @@ function learnMixedLeafNeedle(collector, bag, source) {
6917
6970
  learnNeedle(collector, plaintext, token);
6918
6971
  }
6919
6972
  function asChild(marks, key) {
6920
- return isPlainObject$3(marks) && hasPlainPrototype(marks) ? marks[key] : void 0;
6973
+ return isPlainObject$4(marks) && hasPlainPrototype(marks) ? marks[key] : void 0;
6921
6974
  }
6922
6975
  function asIndex(marks, index) {
6923
6976
  return Array.isArray(marks) ? marks[index] : void 0;
6924
6977
  }
6925
6978
  function preferPositionDecisions(scanned, refused, bag, marks, inferred) {
6926
- if (isPlainObject$3(bag) && hasPlainPrototype(bag) && isPlainObject$3(refused) && isPlainObject$3(scanned)) {
6979
+ if (isPlainObject$4(bag) && hasPlainPrototype(bag) && isPlainObject$4(refused) && isPlainObject$4(scanned)) {
6927
6980
  const out = Object.create(null);
6928
6981
  for (const [k, v] of Object.entries(refused)) out[k] = preferPositionDecisions(scanned[k], v, bag[k], asChild(marks, k), inferred);
6929
6982
  return out;
@@ -7792,12 +7845,12 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
7792
7845
  function recordNestedStackParameterExpressions(secrets, resourceType, resolvedProperties, sourceProperties, rules = TEMPLATE_DERIVED_RULES) {
7793
7846
  if (resourceType !== NESTED_STACK_RESOURCE_TYPE$4) return;
7794
7847
  if (secrets.size === 0) return;
7795
- if (!isPlainObject$3(resolvedProperties) || !isPlainObject$3(sourceProperties)) return;
7848
+ if (!isPlainObject$4(resolvedProperties) || !isPlainObject$4(sourceProperties)) return;
7796
7849
  if (!Object.hasOwn(resolvedProperties, "Parameters")) return;
7797
7850
  if (!Object.hasOwn(sourceProperties, "Parameters")) return;
7798
7851
  const resolvedParameters = resolvedProperties["Parameters"];
7799
7852
  const sourceParameters = sourceProperties["Parameters"];
7800
- if (!isPlainObject$3(resolvedParameters) || !isPlainObject$3(sourceParameters)) return;
7853
+ if (!isPlainObject$4(resolvedParameters) || !isPlainObject$4(sourceParameters)) return;
7801
7854
  const positioned = redactSecretsForState(markSameGenerationBag({ ...resolvedParameters }), secrets, sourceParameters, rules);
7802
7855
  let table = nestedStackParameterExpressions.get(secrets);
7803
7856
  for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
@@ -7829,7 +7882,7 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
7829
7882
  if (typeof resolvedValue !== "string") return void 0;
7830
7883
  const sourceLeaf = sourceParameters[name];
7831
7884
  if (typeof sourceLeaf === "string") return sourceLeaf;
7832
- if (!isPlainObject$3(sourceLeaf)) return void 0;
7885
+ if (!isPlainObject$4(sourceLeaf)) return void 0;
7833
7886
  const written = positioned[name];
7834
7887
  if (typeof written !== "string") return void 0;
7835
7888
  const rendered = intrinsicSkeletonSegments(sourceLeaf)?.map((s) => s === UNKNOWN_PART ? "\0" : s).join("");
@@ -10787,7 +10840,7 @@ function probeFoundSameId(resourceType, a, b) {
10787
10840
  //#region src/provisioning/config-shape.ts
10788
10841
  function readConfigString(container, key, fallback, containerPath, options) {
10789
10842
  if (container === void 0 || container === null) return fallback;
10790
- if (!isPlainObject$2(container) || isUnresolvedIntrinsicContainer(container)) {
10843
+ if (!isPlainObject$3(container) || isUnresolvedIntrinsicContainer(container)) {
10791
10844
  const detail = malformedShapeDetail(container);
10792
10845
  if (options?.onUnusable) {
10793
10846
  const named = fallback === "" ? "" : ` (${fallback})`;
@@ -10827,7 +10880,7 @@ function requireConfigArray(value, path, options) {
10827
10880
  return value;
10828
10881
  }
10829
10882
  function requireConfigObject(value, path, options) {
10830
- if (!isPlainObject$2(value) || isUnresolvedIntrinsicContainer(value)) {
10883
+ if (!isPlainObject$3(value) || isUnresolvedIntrinsicContainer(value)) {
10831
10884
  const detail = malformedShapeDetail(value);
10832
10885
  if (options?.onUnusable) {
10833
10886
  options.onUnusable(`${path} must be an object ${detail}. Leaving this configuration unapplied here; the same value is REFUSED on a template-path create.`);
@@ -10839,7 +10892,7 @@ function requireConfigObject(value, path, options) {
10839
10892
  }
10840
10893
  function configStringRefusal(container, key, fallback, containerPath, options) {
10841
10894
  if (container === void 0 || container === null) return void 0;
10842
- if (!isPlainObject$2(container) || isUnresolvedIntrinsicContainer(container)) return `${containerPath} must be an object ${malformedShapeDetail(container)}`;
10895
+ if (!isPlainObject$3(container) || isUnresolvedIntrinsicContainer(container)) return `${containerPath} must be an object ${malformedShapeDetail(container)}`;
10843
10896
  return configValueRefusal(container[key], fallback, `${containerPath}.${key}`, options);
10844
10897
  }
10845
10898
  function coerceCfnBoolean(value) {
@@ -10852,7 +10905,7 @@ function coerceCfnBoolean(value) {
10852
10905
  }
10853
10906
  function configBooleanRefusal(container, key, containerPath) {
10854
10907
  if (container === void 0 || container === null) return void 0;
10855
- if (!isPlainObject$2(container) || isUnresolvedIntrinsicContainer(container)) return `${containerPath} must be an object ${malformedShapeDetail(container)}`;
10908
+ if (!isPlainObject$3(container) || isUnresolvedIntrinsicContainer(container)) return `${containerPath} must be an object ${malformedShapeDetail(container)}`;
10856
10909
  const value = container[key];
10857
10910
  if (value === void 0) return void 0;
10858
10911
  if (coerceCfnBoolean(value) !== void 0) return void 0;
@@ -10866,7 +10919,7 @@ function coerceCfnInteger(value) {
10866
10919
  }
10867
10920
  function configIntegerRefusal(container, key, containerPath, min, max) {
10868
10921
  if (container === void 0 || container === null) return void 0;
10869
- if (!isPlainObject$2(container) || isUnresolvedIntrinsicContainer(container)) return `${containerPath} must be an object ${malformedShapeDetail(container)}`;
10922
+ if (!isPlainObject$3(container) || isUnresolvedIntrinsicContainer(container)) return `${containerPath} must be an object ${malformedShapeDetail(container)}`;
10870
10923
  const value = container[key];
10871
10924
  if (value === void 0) return void 0;
10872
10925
  const n = coerceCfnInteger(value);
@@ -10880,10 +10933,10 @@ function configValueRefusal(value, fallback, path, options) {
10880
10933
  if (typeof value !== "string" || value.trim() === "") return `${path} must be a non-empty string ${malformedShapeDetail(value)}`;
10881
10934
  }
10882
10935
  function malformedShapeDetail(value) {
10883
- if (isPlainObject$2(value) && isUnresolvedIntrinsicContainer(value)) return `(got ${describe(value)} — nothing substituted it before this call)`;
10936
+ if (isPlainObject$3(value) && isUnresolvedIntrinsicContainer(value)) return `(got ${describe(value)} — nothing substituted it before this call)`;
10884
10937
  return `(got ${describe(value)}) — check for an unresolved intrinsic or a mis-nested template value`;
10885
10938
  }
10886
- function isPlainObject$2(value) {
10939
+ function isPlainObject$3(value) {
10887
10940
  return typeof value === "object" && value !== null && !Array.isArray(value);
10888
10941
  }
10889
10942
  const NAMEABLE_INTRINSIC_KEYS = /* @__PURE__ */ new Set([
@@ -10910,7 +10963,7 @@ function describe(value) {
10910
10963
  if (value === null) return "null";
10911
10964
  if (Array.isArray(value)) return "an array";
10912
10965
  if (typeof value === "string") return value.trim() === "" ? "a blank string" : "a string";
10913
- if (isPlainObject$2(value) && isUnresolvedIntrinsicContainer(value)) {
10966
+ if (isPlainObject$3(value) && isUnresolvedIntrinsicContainer(value)) {
10914
10967
  const key = Object.keys(value)[0];
10915
10968
  return NAMEABLE_INTRINSIC_KEYS.has(key) ? `an unresolved ${key} intrinsic` : "an unresolved intrinsic";
10916
10969
  }
@@ -15683,9 +15736,20 @@ function malformedOrphansForOrphanRefusalMessage(rawStackName, rawRegion, logica
15683
15736
  return orphanRefusal(stackName, region, recovery, `${stackClause(stackName, region)} holds ${logicalIds.length} rollback-orphan record(s) in 'orphans' that cannot be read — ${namedOrphanRows(logicalIds)} — because the record has no string 'logicalId' or shares it with another row, or its 'state' is not an object, names no resource type, has no non-empty string 'physicalId', or holds a 'properties' or 'attributes' map that is not an object. The record is malformed or truncated. ${verbatim} Those records are not inert: they are what the next 'cdkd deploy' may re-adopt into 'resources' and what 'cdkd diff' previews for adoption, so continuing would report success over damage the next command meets.`, "'cdkd orphan' cannot remove such a record itself: it is not in 'resources', so it has no construct path. Repair the record by hand rather than deleting it — it is the only record that an earlier failed deploy left its resource live in AWS.", ORPHANS_DROP_CAVEAT);
15684
15737
  }
15685
15738
 
15739
+ //#endregion
15740
+ //#region src/deployment/assumed-conditions.ts
15741
+ const assumedConditionNames = /* @__PURE__ */ new WeakMap();
15742
+ function recordAssumedConditions(conditions, assumed) {
15743
+ assumedConditionNames.set(conditions, assumed);
15744
+ }
15745
+ function conditionsAssumedFalse(conditions) {
15746
+ return assumedConditionNames.get(conditions) ?? /* @__PURE__ */ new Set();
15747
+ }
15748
+
15686
15749
  //#endregion
15687
15750
  //#region src/deployment/masked-property-fingerprints.ts
15688
15751
  const FINGERPRINT_LAYOUT$1 = 1;
15752
+ const INPUT_FINGERPRINT_LAYOUT = 2;
15689
15753
  function canonicalJson$2(value) {
15690
15754
  if (value === void 0) return "null";
15691
15755
  if (Array.isArray(value)) return `[${value.map(canonicalJson$2).join(",")}]`;
@@ -15697,6 +15761,20 @@ function canonicalJson$2(value) {
15697
15761
  }
15698
15762
  const REFUSED_FINGERPRINT = "refused:secret-in-template";
15699
15763
  const FINGERPRINT_PREFIX = "sha256:";
15764
+ const INPUT_FINGERPRINT_PREFIX = "inputs-sha256:";
15765
+ const TEXT_HALF_SEPARATOR = "+";
15766
+ function splitInputFingerprint(entry) {
15767
+ const at = entry.indexOf(TEXT_HALF_SEPARATOR);
15768
+ if (at < 0) return {
15769
+ input: entry,
15770
+ text: void 0
15771
+ };
15772
+ const text = entry.slice(at + 1);
15773
+ return {
15774
+ input: entry.slice(0, at),
15775
+ text: text.startsWith(FINGERPRINT_PREFIX) ? text : void 0
15776
+ };
15777
+ }
15700
15778
  function templateCarriesNeedle(templateValue, secrets) {
15701
15779
  const text = canonicalJson$2(templateValue);
15702
15780
  for (const needle of printingCorpusOf(secrets).keys()) {
@@ -15712,6 +15790,725 @@ function maskedPropertyFingerprint(templateValue) {
15712
15790
  })).digest("hex");
15713
15791
  return `${FINGERPRINT_PREFIX}${digest}`;
15714
15792
  }
15793
+ var UnknownInput = class extends Error {};
15794
+ function isPlainObject$2(value) {
15795
+ return value !== null && typeof value === "object" && !Array.isArray(value);
15796
+ }
15797
+ const DYNAMIC_REFERENCE_OPEN = "{{resolve:";
15798
+ const NESTED_STACK_TYPE$2 = "AWS::CloudFormation::Stack";
15799
+ const NESTED_OUTPUT_PREFIX = "Outputs.";
15800
+ function carriesSecretValue(value, corpora) {
15801
+ if (carriesSecretMask(value)) return true;
15802
+ const text = canonicalJson$2(value);
15803
+ if (text.includes(DYNAMIC_REFERENCE_OPEN)) return true;
15804
+ for (const corpus of corpora) {
15805
+ if (corpus === void 0) continue;
15806
+ for (const needle of printingCorpusOf(corpus).keys()) {
15807
+ if (needle.length === 0) continue;
15808
+ if (text.includes(needle) || text.includes(JSON.stringify(needle).slice(1, -1))) return true;
15809
+ }
15810
+ }
15811
+ return false;
15812
+ }
15813
+ function parameterInputsFor(args) {
15814
+ const declared = isPlainObject$2(args.template.Parameters) ? args.template.Parameters : {};
15815
+ const values = args.values ?? {};
15816
+ const inputs = /* @__PURE__ */ new Map();
15817
+ const bound = {};
15818
+ for (const name of Object.keys(declared)) {
15819
+ const definition = declared[name];
15820
+ if (args.unbound?.has(name) || !Object.hasOwn(values, name)) {
15821
+ inputs.set(name, { kind: "unknown" });
15822
+ continue;
15823
+ }
15824
+ const value = values[name];
15825
+ let secret = isPlainObject$2(definition) && (definition["NoEcho"] === true || definition["NoEcho"] === "true") || carriesSecretValue(value, []);
15826
+ if (!secret && args.nestedChild === true && args.supplied !== void 0) {
15827
+ if (Object.hasOwn(args.supplied, name)) {
15828
+ const passed = args.passedClasses?.get(name);
15829
+ if (passed === "unknown") {
15830
+ inputs.set(name, { kind: "unknown" });
15831
+ continue;
15832
+ }
15833
+ if (passed !== "clean") secret = true;
15834
+ }
15835
+ }
15836
+ if (secret) inputs.set(name, { kind: "secret" });
15837
+ else {
15838
+ inputs.set(name, {
15839
+ kind: "value",
15840
+ value
15841
+ });
15842
+ bound[name] = value;
15843
+ }
15844
+ }
15845
+ return {
15846
+ parameterInput: (name) => inputs.get(name) ?? { kind: "unknown" },
15847
+ bound
15848
+ };
15849
+ }
15850
+ function newShared() {
15851
+ return {
15852
+ steps: 0,
15853
+ passed: /* @__PURE__ */ new Map(),
15854
+ outputs: /* @__PURE__ */ new Map(),
15855
+ rowsPassed: /* @__PURE__ */ new Map()
15856
+ };
15857
+ }
15858
+ function subPlaceholders(text) {
15859
+ const names = [];
15860
+ for (const match of text.matchAll(/\$\{([^}]*)\}/g)) {
15861
+ const body = match[1] ?? "";
15862
+ if (body.startsWith("!") || body.length === 0) continue;
15863
+ if (!names.includes(body)) names.push(body);
15864
+ }
15865
+ return names;
15866
+ }
15867
+ function intrinsicKey(value) {
15868
+ const keys = Object.keys(value);
15869
+ if (keys.length !== 1) return void 0;
15870
+ const key = keys[0];
15871
+ return key === "Ref" || key.startsWith("Fn::") ? key : void 0;
15872
+ }
15873
+ const OPAQUE_ATTRIBUTE_TYPES = /* @__PURE__ */ new Set(["AWS::CloudFormation::CustomResource", NESTED_STACK_TYPE$2]);
15874
+ function hasOpaqueAttributes(logicalId, walk) {
15875
+ const definition = walk.resources[logicalId];
15876
+ const type = isPlainObject$2(definition) ? definition["Type"] : void 0;
15877
+ return typeof type === "string" && (type.startsWith("Custom::") || OPAQUE_ATTRIBUTE_TYPES.has(type));
15878
+ }
15879
+ function getAttTarget(operand) {
15880
+ if (Array.isArray(operand) && typeof operand[0] === "string") return operand[0];
15881
+ if (typeof operand === "string" && operand.includes(".")) return operand.split(".")[0];
15882
+ }
15883
+ function taintOf(logicalId, walk) {
15884
+ const cached = walk.taint.get(logicalId);
15885
+ if (cached !== void 0) return cached;
15886
+ if (walk.inProgress.has(logicalId)) return "tainted";
15887
+ walk.inProgress.add(logicalId);
15888
+ let unknown = false;
15889
+ const nameTaint = (name) => {
15890
+ if (name.startsWith("AWS::")) return "clean";
15891
+ if (Object.hasOwn(walk.resources, name)) return taintOf(name, walk);
15892
+ if (Object.hasOwn(walk.parameters, name)) {
15893
+ const input = walk.sources.parameterInput(name);
15894
+ return input.kind === "value" ? "clean" : input.kind === "secret" ? "tainted" : "unknown";
15895
+ }
15896
+ return "tainted";
15897
+ };
15898
+ const visit = (value) => {
15899
+ if (typeof value === "string") return value.includes(DYNAMIC_REFERENCE_OPEN);
15900
+ if (Array.isArray(value)) return value.some(visit);
15901
+ if (!isPlainObject$2(value)) return false;
15902
+ const key = intrinsicKey(value);
15903
+ const operand = key === void 0 ? void 0 : value[key];
15904
+ let verdict = "clean";
15905
+ if (key === "Ref" && typeof operand === "string") verdict = nameTaint(operand);
15906
+ else if (key === "Fn::GetAtt") {
15907
+ const target = getAttTarget(operand);
15908
+ verdict = target === void 0 || Object.hasOwn(walk.resources, target) && hasOpaqueAttributes(target, walk) ? "tainted" : nameTaint(target);
15909
+ } else if (key === "Fn::ImportValue" || key === "Fn::GetStackOutput") verdict = "tainted";
15910
+ else if (key === "Fn::FindInMap" && mapReadClass(operand, walk.sources.template) !== "clean") verdict = "tainted";
15911
+ else if (key === "Fn::Sub") {
15912
+ const text = Array.isArray(operand) ? operand[0] : operand;
15913
+ const vars = Array.isArray(operand) && isPlainObject$2(operand[1]) ? operand[1] : {};
15914
+ if (typeof text === "string") for (const name of subPlaceholders(text)) {
15915
+ if (Object.hasOwn(vars, name)) continue;
15916
+ const owner = name.includes(".") ? name.split(".")[0] : name;
15917
+ const t = name.includes(".") && Object.hasOwn(walk.resources, owner) && hasOpaqueAttributes(owner, walk) ? "tainted" : nameTaint(owner);
15918
+ if (t === "tainted") return true;
15919
+ if (t === "unknown") unknown = true;
15920
+ }
15921
+ }
15922
+ if (verdict === "tainted") return true;
15923
+ if (verdict === "unknown") unknown = true;
15924
+ return Object.values(value).some(visit);
15925
+ };
15926
+ const definition = walk.resources[logicalId];
15927
+ const result = visit(isPlainObject$2(definition) ? definition["Properties"] : void 0) ? "tainted" : unknown ? "unknown" : "clean";
15928
+ walk.inProgress.delete(logicalId);
15929
+ walk.taint.set(logicalId, result);
15930
+ return result;
15931
+ }
15932
+ function conditionInput(name, walk) {
15933
+ const closure = conditionClosure(name, walk);
15934
+ if (closure.unknown || closure.unread) return "unknown";
15935
+ if (closure.secret) return "secret";
15936
+ const conditions = walk.sources.conditions;
15937
+ if (conditions === void 0 || !Object.hasOwn(conditions, name)) return "unknown";
15938
+ if (conditionsAssumedFalse(conditions).has(name)) return "unknown";
15939
+ const verdict = conditions[name];
15940
+ return typeof verdict === "boolean" ? verdict : "unknown";
15941
+ }
15942
+ function conditionClosure(name, walk) {
15943
+ const definitions = isPlainObject$2(walk.sources.template.Conditions) ? walk.sources.template.Conditions : {};
15944
+ let secret = false;
15945
+ let unknown = false;
15946
+ let unread = false;
15947
+ const seen = /* @__PURE__ */ new Set();
15948
+ const pending = [name];
15949
+ const visit = (value) => {
15950
+ if (typeof value === "string") {
15951
+ if (value.includes(DYNAMIC_REFERENCE_OPEN)) secret = true;
15952
+ return;
15953
+ }
15954
+ if (Array.isArray(value)) {
15955
+ value.forEach(visit);
15956
+ return;
15957
+ }
15958
+ if (!isPlainObject$2(value)) return;
15959
+ const keys = Object.keys(value);
15960
+ if (keys.length === 1 && keys[0] === "Condition" && typeof value["Condition"] === "string") {
15961
+ pending.push(value["Condition"]);
15962
+ return;
15963
+ }
15964
+ const classifyName = (ref) => {
15965
+ if (ref.startsWith("AWS::")) return;
15966
+ if (!Object.hasOwn(walk.parameters, ref)) {
15967
+ unknown = true;
15968
+ return;
15969
+ }
15970
+ const input = walk.sources.parameterInput(ref);
15971
+ if (input.kind === "secret") secret = true;
15972
+ if (input.kind === "unknown") unread = true;
15973
+ };
15974
+ if (keys.length === 1 && keys[0] === "Ref" && typeof value["Ref"] === "string") {
15975
+ classifyName(value["Ref"]);
15976
+ return;
15977
+ }
15978
+ const key = keys.length === 1 ? keys[0] : void 0;
15979
+ if (key === "Fn::FindInMap") {
15980
+ const read = mapReadClass(value["Fn::FindInMap"], walk.sources.template);
15981
+ if (read === "secret") secret = true;
15982
+ if (read === "unknown") unknown = true;
15983
+ }
15984
+ if (key === "Fn::ImportValue" || key === "Fn::GetStackOutput" || key === "Fn::GetAtt") {
15985
+ secret = true;
15986
+ return;
15987
+ }
15988
+ if (key === "Fn::Sub") {
15989
+ const operand = value["Fn::Sub"];
15990
+ const text = Array.isArray(operand) ? operand[0] : operand;
15991
+ const vars = Array.isArray(operand) && isPlainObject$2(operand[1]) ? operand[1] : {};
15992
+ if (typeof text === "string") for (const name of subPlaceholders(text)) {
15993
+ if (Object.hasOwn(vars, name)) continue;
15994
+ if (name.includes(".") && !name.startsWith("AWS::")) secret = true;
15995
+ else classifyName(name);
15996
+ }
15997
+ }
15998
+ Object.values(value).forEach(visit);
15999
+ };
16000
+ while (pending.length > 0) {
16001
+ const current = pending.pop();
16002
+ if (seen.has(current)) continue;
16003
+ seen.add(current);
16004
+ if (!Object.hasOwn(definitions, current)) {
16005
+ unknown = true;
16006
+ continue;
16007
+ }
16008
+ visit(definitions[current]);
16009
+ }
16010
+ return {
16011
+ secret,
16012
+ unknown,
16013
+ unread
16014
+ };
16015
+ }
16016
+ function mapReadClass(operand, template) {
16017
+ const mapName = Array.isArray(operand) ? operand[0] : void 0;
16018
+ if (typeof mapName !== "string") return "unknown";
16019
+ const mappings = template.Mappings;
16020
+ const map = isPlainObject$2(mappings) && Object.hasOwn(mappings, mapName) ? mappings[mapName] : void 0;
16021
+ if (!isPlainObject$2(map)) return "unknown";
16022
+ return carriesSecretValue(map, []) ? "secret" : "clean";
16023
+ }
16024
+ async function resolvedInput(node, walk) {
16025
+ let resolved;
16026
+ try {
16027
+ resolved = await walk.sources.resolve(node);
16028
+ } catch {
16029
+ throw new UnknownInput();
16030
+ }
16031
+ if (resolved.keepAsWritten === true || carriesSecretValue(resolved.value, [resolved.secrets])) return {
16032
+ form: node,
16033
+ concrete: false
16034
+ };
16035
+ return {
16036
+ form: resolved.value,
16037
+ concrete: true
16038
+ };
16039
+ }
16040
+ async function nameInput(name, node, walk) {
16041
+ if (name === "AWS::NoValue") return {
16042
+ form: node,
16043
+ concrete: false
16044
+ };
16045
+ if (name.startsWith("AWS::")) return resolvedInput(node, walk);
16046
+ if (Object.hasOwn(walk.resources, name)) {
16047
+ const taint = taintOf(name, walk);
16048
+ if (taint === "unknown") throw new UnknownInput();
16049
+ if (taint === "tainted") return {
16050
+ form: node,
16051
+ concrete: false
16052
+ };
16053
+ return resolvedInput(node, walk);
16054
+ }
16055
+ if (Object.hasOwn(walk.parameters, name)) {
16056
+ const input = walk.sources.parameterInput(name);
16057
+ if (input.kind === "unknown") throw new UnknownInput();
16058
+ if (input.kind === "secret") return {
16059
+ form: node,
16060
+ concrete: false
16061
+ };
16062
+ return {
16063
+ form: input.value,
16064
+ concrete: true
16065
+ };
16066
+ }
16067
+ return {
16068
+ form: node,
16069
+ concrete: false
16070
+ };
16071
+ }
16072
+ async function inputForms(values, walk) {
16073
+ const parts = [];
16074
+ for (const element of values) parts.push(await inputForm(element, walk));
16075
+ return parts;
16076
+ }
16077
+ async function inputForm(value, walk) {
16078
+ if (typeof value === "string") return {
16079
+ form: value,
16080
+ concrete: !value.includes(DYNAMIC_REFERENCE_OPEN)
16081
+ };
16082
+ if (Array.isArray(value)) {
16083
+ const parts = await inputForms(value, walk);
16084
+ return {
16085
+ form: parts.map((p) => p.form),
16086
+ concrete: parts.every((p) => p.concrete)
16087
+ };
16088
+ }
16089
+ if (!isPlainObject$2(value)) return {
16090
+ form: value,
16091
+ concrete: true
16092
+ };
16093
+ const key = intrinsicKey(value);
16094
+ if (key === void 0) {
16095
+ const entries = Object.keys(value);
16096
+ const parts = await inputForms(entries.map((k) => value[k]), walk);
16097
+ return {
16098
+ form: Object.fromEntries(entries.map((k, i) => [k, parts[i].form])),
16099
+ concrete: parts.every((p) => p.concrete)
16100
+ };
16101
+ }
16102
+ const operand = value[key];
16103
+ switch (key) {
16104
+ case "Ref": return typeof operand === "string" ? nameInput(operand, value, walk) : {
16105
+ form: value,
16106
+ concrete: false
16107
+ };
16108
+ case "Fn::GetAtt": {
16109
+ const target = getAttTarget(operand);
16110
+ if (target !== void 0 && isNestedStackRow(target, walk)) return nestedOutputInput(target, getAttAttribute(operand, target), value, walk);
16111
+ if (target === void 0 || !Object.hasOwn(walk.resources, target) || hasOpaqueAttributes(target, walk)) return {
16112
+ form: value,
16113
+ concrete: false
16114
+ };
16115
+ if (Array.isArray(operand) && operand.length > 1 && typeof operand[1] !== "string") {
16116
+ const attribute = await inputForm(operand[1], walk);
16117
+ if (!attribute.concrete) return {
16118
+ form: { [key]: [operand[0], attribute.form] },
16119
+ concrete: false
16120
+ };
16121
+ }
16122
+ return nameInput(target, value, walk);
16123
+ }
16124
+ case "Fn::If": {
16125
+ if (!Array.isArray(operand) || typeof operand[0] !== "string") {
16126
+ const args = await inputForm(operand, walk);
16127
+ return {
16128
+ form: { [key]: args.form },
16129
+ concrete: false
16130
+ };
16131
+ }
16132
+ const verdict = conditionInput(operand[0], walk);
16133
+ if (verdict === "unknown") throw new UnknownInput();
16134
+ if (verdict === "secret") {
16135
+ const args = await inputForm(operand.slice(1), walk);
16136
+ return {
16137
+ form: { [key]: [operand[0], ...args.form] },
16138
+ concrete: false
16139
+ };
16140
+ }
16141
+ return inputForm(verdict ? operand[1] : operand[2], walk);
16142
+ }
16143
+ case "Fn::Sub": {
16144
+ const text = Array.isArray(operand) ? operand[0] : operand;
16145
+ if (typeof text !== "string") {
16146
+ const args = await inputForm(operand, walk);
16147
+ return {
16148
+ form: { [key]: args.form },
16149
+ concrete: false
16150
+ };
16151
+ }
16152
+ const explicit = Array.isArray(operand) && isPlainObject$2(operand[1]) ? operand[1] : {};
16153
+ const vars = await inputForm(explicit, walk);
16154
+ const placeholders = [];
16155
+ let concrete = vars.concrete && !text.includes(DYNAMIC_REFERENCE_OPEN);
16156
+ for (const name of subPlaceholders(text)) {
16157
+ if (Object.hasOwn(explicit, name)) continue;
16158
+ const dot = name.indexOf(".");
16159
+ const part = dot > 0 && !name.startsWith("AWS::") && isNestedStackRow(name.slice(0, dot), walk) ? await nestedOutputInput(name.slice(0, dot), name.slice(dot + 1), { "Fn::GetAtt": [name.slice(0, dot), name.slice(dot + 1)] }, walk) : dot > 0 && !name.startsWith("AWS::") ? Object.hasOwn(walk.resources, name.slice(0, dot)) && !hasOpaqueAttributes(name.slice(0, dot), walk) ? await nameInput(name.slice(0, dot), { "Fn::GetAtt": [name.slice(0, dot), name.slice(dot + 1)] }, walk) : {
16160
+ form: { "Fn::GetAtt": [name.slice(0, dot), name.slice(dot + 1)] },
16161
+ concrete: false
16162
+ } : await nameInput(name, { Ref: name }, walk);
16163
+ placeholders.push([name, part.form]);
16164
+ concrete &&= part.concrete;
16165
+ }
16166
+ return {
16167
+ form: { [key]: [
16168
+ text,
16169
+ vars.form,
16170
+ Object.fromEntries(placeholders)
16171
+ ] },
16172
+ concrete
16173
+ };
16174
+ }
16175
+ case "Fn::ImportValue":
16176
+ case "Fn::GetStackOutput":
16177
+ case "Fn::FindInMap":
16178
+ case "Fn::GetAZs": {
16179
+ const args = await inputForm(operand, walk);
16180
+ if (!args.concrete) return {
16181
+ form: { [key]: args.form },
16182
+ concrete: false
16183
+ };
16184
+ const resolved = await resolvedInput(value, walk);
16185
+ return resolved.concrete ? resolved : {
16186
+ form: { [key]: args.form },
16187
+ concrete: false
16188
+ };
16189
+ }
16190
+ default: {
16191
+ const args = await inputForm(operand, walk);
16192
+ return {
16193
+ form: { [key]: args.form },
16194
+ concrete: args.concrete
16195
+ };
16196
+ }
16197
+ }
16198
+ }
16199
+ function newWalk(sources, nested = {
16200
+ stackChain: /* @__PURE__ */ new Set(),
16201
+ shared: newShared()
16202
+ }) {
16203
+ return {
16204
+ sources,
16205
+ resources: isPlainObject$2(sources.template.Resources) ? sources.template.Resources : {},
16206
+ parameters: isPlainObject$2(sources.template.Parameters) ? sources.template.Parameters : {},
16207
+ taint: /* @__PURE__ */ new Map(),
16208
+ inProgress: /* @__PURE__ */ new Set(),
16209
+ stackChain: nested.stackChain,
16210
+ shared: nested.shared
16211
+ };
16212
+ }
16213
+ const NESTED_OUTPUT_ORDER = {
16214
+ clean: 0,
16215
+ unread: 1,
16216
+ unknown: 2,
16217
+ secret: 3
16218
+ };
16219
+ function worseOf(a, b) {
16220
+ return NESTED_OUTPUT_ORDER[a] >= NESTED_OUTPUT_ORDER[b] ? a : b;
16221
+ }
16222
+ const MAX_NESTED_OUTPUT_DEPTH = 32;
16223
+ const MAX_NESTED_OUTPUT_STEPS = 1e4;
16224
+ function passedKey(passed) {
16225
+ return JSON.stringify([...passed.entries()]);
16226
+ }
16227
+ function isNestedStackRow(logicalId, walk) {
16228
+ if (!Object.hasOwn(walk.resources, logicalId)) return false;
16229
+ const definition = walk.resources[logicalId];
16230
+ return isPlainObject$2(definition) && definition["Type"] === NESTED_STACK_TYPE$2;
16231
+ }
16232
+ function getAttAttribute(operand, target) {
16233
+ if (Array.isArray(operand)) return operand.length === 2 && typeof operand[1] === "string" ? operand[1] : void 0;
16234
+ return typeof operand === "string" ? operand.slice(target.length + 1) : void 0;
16235
+ }
16236
+ function rowParameters(definition) {
16237
+ const properties = isPlainObject$2(definition) ? definition["Properties"] : void 0;
16238
+ if (properties === void 0) return {};
16239
+ if (!isPlainObject$2(properties)) return "unknown";
16240
+ const parameters = properties["Parameters"];
16241
+ if (parameters === void 0) return {};
16242
+ if (!isPlainObject$2(parameters) || intrinsicKey(parameters) !== void 0) return "unknown";
16243
+ return parameters;
16244
+ }
16245
+ function childParameterInputs(template, passed) {
16246
+ const declared = isPlainObject$2(template.Parameters) ? template.Parameters : {};
16247
+ const inputs = /* @__PURE__ */ new Map();
16248
+ for (const name of Object.keys(declared)) {
16249
+ const definition = declared[name];
16250
+ if (isPlainObject$2(definition) && (definition["NoEcho"] === true || definition["NoEcho"] === "true")) inputs.set(name, { kind: "secret" });
16251
+ else if (passed.has(name)) {
16252
+ const passedClass = passed.get(name);
16253
+ inputs.set(name, passedClass === "clean" ? {
16254
+ kind: "value",
16255
+ value: void 0
16256
+ } : passedClass === "unknown" ? { kind: "unknown" } : { kind: "secret" });
16257
+ } else if (isPlainObject$2(definition) && Object.hasOwn(definition, "Default") && !carriesSecretValue(definition["Default"], [])) inputs.set(name, {
16258
+ kind: "value",
16259
+ value: definition["Default"]
16260
+ });
16261
+ else inputs.set(name, { kind: "secret" });
16262
+ }
16263
+ return (name) => inputs.get(name) ?? { kind: "secret" };
16264
+ }
16265
+ function taintClass(taint) {
16266
+ return taint === "clean" ? "clean" : taint === "tainted" ? "secret" : "unread";
16267
+ }
16268
+ function closureClass(closure) {
16269
+ if (closure.secret) return "secret";
16270
+ if (closure.unknown) return "unknown";
16271
+ return closure.unread ? "unread" : "clean";
16272
+ }
16273
+ async function childOutputClass(loaded, outputName, passed, chain, shared) {
16274
+ if (loaded === void 0 || !isPlainObject$2(loaded.template)) return "unknown";
16275
+ const scopeKey = JSON.stringify([loaded.identity, passedKey(passed)]);
16276
+ const memoKey = JSON.stringify([scopeKey, outputName]);
16277
+ const memo = shared.outputs.get(memoKey);
16278
+ if (memo !== void 0) return memo;
16279
+ const outputClass = await classifyChildOutput(loaded, outputName, passed, chain, shared, scopeKey);
16280
+ shared.outputs.set(memoKey, outputClass);
16281
+ return outputClass;
16282
+ }
16283
+ async function classifyChildOutput(loaded, outputName, passed, chain, shared, scopeKey) {
16284
+ if (++shared.steps > MAX_NESTED_OUTPUT_STEPS) return "unknown";
16285
+ if (chain.includes(loaded.identity) || chain.length >= MAX_NESTED_OUTPUT_DEPTH) return "unknown";
16286
+ const template = loaded.template;
16287
+ const output = (isPlainObject$2(template.Outputs) ? template.Outputs : {})[outputName];
16288
+ if (!isPlainObject$2(output) || !Object.hasOwn(output, "Value")) return "unknown";
16289
+ const scope = {
16290
+ walk: newWalk({
16291
+ template,
16292
+ parameterInput: childParameterInputs(template, passed),
16293
+ resolve: () => Promise.reject(/* @__PURE__ */ new Error("a nested output is classified, never resolved"))
16294
+ }),
16295
+ childTemplate: loaded.childTemplate,
16296
+ chain: [...chain, loaded.identity],
16297
+ rows: /* @__PURE__ */ new Set(),
16298
+ key: scopeKey,
16299
+ shared
16300
+ };
16301
+ let outputClass = "clean";
16302
+ if (Object.hasOwn(output, "Condition")) {
16303
+ const condition = output["Condition"];
16304
+ outputClass = typeof condition === "string" ? closureClass(conditionClosure(condition, scope.walk)) : "unknown";
16305
+ }
16306
+ return worseOf(outputClass, await expressionClass(output["Value"], scope));
16307
+ }
16308
+ function nameClass(name, scope) {
16309
+ if (name.startsWith("AWS::")) return "clean";
16310
+ const walk = scope.walk;
16311
+ if (Object.hasOwn(walk.resources, name)) return taintClass(taintOf(name, walk));
16312
+ if (Object.hasOwn(walk.parameters, name)) {
16313
+ const input = walk.sources.parameterInput(name);
16314
+ return input.kind === "value" ? "clean" : input.kind === "secret" ? "secret" : "unread";
16315
+ }
16316
+ return "secret";
16317
+ }
16318
+ async function attributeClass(target, attribute, scope) {
16319
+ const walk = scope.walk;
16320
+ if (!Object.hasOwn(walk.resources, target)) return "secret";
16321
+ if (isNestedStackRow(target, walk)) {
16322
+ if (attribute === void 0 || !attribute.startsWith(NESTED_OUTPUT_PREFIX)) return "unknown";
16323
+ if (scope.rows.has(target)) return "unknown";
16324
+ const parameters = rowParameters(walk.resources[target]);
16325
+ if (parameters === "unknown") return "unknown";
16326
+ const rowKey = JSON.stringify([scope.key, target]);
16327
+ let passed = scope.shared.rowsPassed.get(rowKey);
16328
+ if (passed === void 0) {
16329
+ const inner = {
16330
+ ...scope,
16331
+ rows: /* @__PURE__ */ new Set([...scope.rows, target])
16332
+ };
16333
+ const classes = /* @__PURE__ */ new Map();
16334
+ for (const [name, expression] of Object.entries(parameters)) {
16335
+ const passedClass = await expressionClass(expression, inner);
16336
+ classes.set(name, passedClass === "clean" ? "clean" : passedClass === "unread" ? "unknown" : "secret");
16337
+ }
16338
+ scope.shared.rowsPassed.set(rowKey, classes);
16339
+ passed = classes;
16340
+ }
16341
+ let loaded;
16342
+ try {
16343
+ loaded = scope.childTemplate(target);
16344
+ } catch {
16345
+ loaded = void 0;
16346
+ }
16347
+ return childOutputClass(loaded, attribute.slice(8), passed, scope.chain, scope.shared);
16348
+ }
16349
+ if (hasOpaqueAttributes(target, walk)) return "unknown";
16350
+ return taintClass(taintOf(target, walk));
16351
+ }
16352
+ async function expressionClass(value, scope) {
16353
+ if (typeof value === "string") return value.includes(DYNAMIC_REFERENCE_OPEN) ? "secret" : "clean";
16354
+ const all = async (values) => {
16355
+ let result = "clean";
16356
+ for (const element of values) result = worseOf(result, await expressionClass(element, scope));
16357
+ return result;
16358
+ };
16359
+ if (Array.isArray(value)) return all(value);
16360
+ if (!isPlainObject$2(value)) return "clean";
16361
+ const key = intrinsicKey(value);
16362
+ if (key === void 0) return all(Object.values(value));
16363
+ const operand = value[key];
16364
+ switch (key) {
16365
+ case "Ref": return typeof operand === "string" ? nameClass(operand, scope) : "unknown";
16366
+ case "Fn::GetAtt": {
16367
+ const target = getAttTarget(operand);
16368
+ if (target === void 0) return "secret";
16369
+ const attribute = getAttAttribute(operand, target);
16370
+ return worseOf(attribute === void 0 && Array.isArray(operand) ? await all(operand.slice(1)) : "clean", await attributeClass(target, attribute, scope));
16371
+ }
16372
+ case "Fn::Sub": {
16373
+ const text = Array.isArray(operand) ? operand[0] : operand;
16374
+ if (typeof text !== "string") return worseOf("unknown", await expressionClass(operand, scope));
16375
+ const vars = Array.isArray(operand) && isPlainObject$2(operand[1]) ? operand[1] : {};
16376
+ let result = text.includes(DYNAMIC_REFERENCE_OPEN) ? "secret" : "clean";
16377
+ result = worseOf(result, await all(Object.values(vars)));
16378
+ for (const name of subPlaceholders(text)) {
16379
+ if (Object.hasOwn(vars, name)) continue;
16380
+ const dot = name.indexOf(".");
16381
+ result = worseOf(result, dot > 0 && !name.startsWith("AWS::") ? await attributeClass(name.slice(0, dot), name.slice(dot + 1), scope) : nameClass(name, scope));
16382
+ }
16383
+ return result;
16384
+ }
16385
+ case "Fn::If":
16386
+ if (!Array.isArray(operand) || operand.length !== 3 || typeof operand[0] !== "string") return worseOf("unknown", await expressionClass(operand, scope));
16387
+ return worseOf(closureClass(conditionClosure(operand[0], scope.walk)), await all(operand.slice(1)));
16388
+ case "Fn::ImportValue":
16389
+ case "Fn::GetStackOutput": return "secret";
16390
+ case "Fn::FindInMap": {
16391
+ const read = mapReadClass(operand, scope.walk.sources.template);
16392
+ if (read === "unknown") return worseOf("unknown", await all([operand]));
16393
+ return worseOf(read, await all(operand.slice(1)));
16394
+ }
16395
+ default: return expressionClass(operand, scope);
16396
+ }
16397
+ }
16398
+ async function stackOutputClass(stackLogicalId, attribute, walk) {
16399
+ const loader = walk.sources.childTemplate;
16400
+ if (loader === void 0 || !isNestedStackRow(stackLogicalId, walk)) return "unknown";
16401
+ if (attribute === void 0 || !attribute.startsWith(NESTED_OUTPUT_PREFIX)) return "unknown";
16402
+ if (walk.stackChain.has(stackLogicalId)) return "unknown";
16403
+ const parameters = rowParameters(walk.resources[stackLogicalId]);
16404
+ if (parameters === "unknown") return "unknown";
16405
+ let passed = walk.shared.passed.get(stackLogicalId);
16406
+ if (passed === void 0) {
16407
+ if (++walk.shared.steps > MAX_NESTED_OUTPUT_STEPS) return "unknown";
16408
+ passed = await classifyPassed(parameters, walk.sources, {
16409
+ stackChain: /* @__PURE__ */ new Set([...walk.stackChain, stackLogicalId]),
16410
+ shared: walk.shared
16411
+ });
16412
+ walk.shared.passed.set(stackLogicalId, passed);
16413
+ }
16414
+ let loaded;
16415
+ try {
16416
+ loaded = loader(stackLogicalId);
16417
+ } catch {
16418
+ loaded = void 0;
16419
+ }
16420
+ return childOutputClass(loaded, attribute.slice(8), passed, [], walk.shared);
16421
+ }
16422
+ async function nestedOutputInput(stackLogicalId, attribute, node, walk) {
16423
+ const outputClass = await stackOutputClass(stackLogicalId, attribute, walk);
16424
+ if (outputClass === "unread") throw new UnknownInput();
16425
+ if (outputClass !== "clean") return {
16426
+ form: node,
16427
+ concrete: false
16428
+ };
16429
+ return resolvedInput(node, walk);
16430
+ }
16431
+ async function maskedInputFingerprint(templateValue, sources) {
16432
+ let form;
16433
+ try {
16434
+ form = (await inputForm(templateValue, newWalk(sources))).form;
16435
+ } catch (error) {
16436
+ if (error instanceof UnknownInput) return void 0;
16437
+ throw error;
16438
+ }
16439
+ const digest = createHash("sha256").update(canonicalJson$2({
16440
+ layout: INPUT_FINGERPRINT_LAYOUT,
16441
+ value: form
16442
+ })).digest("hex");
16443
+ return `${INPUT_FINGERPRINT_PREFIX}${digest}${TEXT_HALF_SEPARATOR}${maskedPropertyFingerprint(templateValue)}`;
16444
+ }
16445
+ async function classifyPassedParameters(parameters, sources) {
16446
+ return classifyPassed(parameters, sources, {
16447
+ stackChain: /* @__PURE__ */ new Set(),
16448
+ shared: newShared()
16449
+ });
16450
+ }
16451
+ async function classifyPassed(parameters, sources, nested) {
16452
+ const classes = /* @__PURE__ */ new Map();
16453
+ if (!isPlainObject$2(parameters)) return classes;
16454
+ for (const [name, expression] of Object.entries(parameters)) {
16455
+ let passedClass;
16456
+ try {
16457
+ passedClass = (await inputForm(expression, newWalk(sources, nested))).concrete ? "clean" : "secret";
16458
+ } catch {
16459
+ passedClass = "unknown";
16460
+ }
16461
+ classes.set(name, passedClass);
16462
+ }
16463
+ return classes;
16464
+ }
16465
+ const passedParameterClasses = /* @__PURE__ */ new WeakMap();
16466
+ function recordPassedParameterClasses(bag, classes) {
16467
+ passedParameterClasses.set(bag, classes);
16468
+ }
16469
+ function passedParameterClassesOf(bag) {
16470
+ return bag === void 0 ? void 0 : passedParameterClasses.get(bag);
16471
+ }
16472
+ function inputFingerprinter(templateProps, sources) {
16473
+ const memo = /* @__PURE__ */ new Map();
16474
+ return (key) => {
16475
+ let pending = memo.get(key);
16476
+ if (pending === void 0) {
16477
+ pending = Object.hasOwn(templateProps, key) ? maskedInputFingerprint(templateProps[key], sources).catch(() => void 0) : Promise.resolve(void 0);
16478
+ memo.set(key, pending);
16479
+ }
16480
+ return pending;
16481
+ };
16482
+ }
16483
+ function possiblyMaskedKeys(resolvedProps, corpora) {
16484
+ const needles = /* @__PURE__ */ new Set();
16485
+ for (const corpus of corpora) {
16486
+ if (corpus === void 0) continue;
16487
+ for (const needle of printingCorpusOf(corpus).keys()) if (needle.length > 0) needles.add(needle);
16488
+ }
16489
+ const short = [...needles].filter((needle) => needle.length < 4);
16490
+ const long = [...needles].filter((needle) => needle.length >= 4);
16491
+ const wholeShortLeaf = (value) => {
16492
+ if (typeof value === "string") return short.includes(value);
16493
+ if (Array.isArray(value)) return value.some(wholeShortLeaf);
16494
+ if (isPlainObject$2(value)) return Object.values(value).some(wholeShortLeaf);
16495
+ return false;
16496
+ };
16497
+ return Object.keys(resolvedProps).filter((key) => {
16498
+ const value = resolvedProps[key];
16499
+ if (carriesSecretMask(value) || wholeShortLeaf(value)) return true;
16500
+ const text = canonicalJson$2(value);
16501
+ return long.some((needle) => text.includes(needle) || text.includes(JSON.stringify(needle).slice(1, -1)));
16502
+ });
16503
+ }
16504
+ async function maskedInputFingerprintsFor(keys, fingerprinter) {
16505
+ const entries = [];
16506
+ for (const key of keys) {
16507
+ const fingerprint = await fingerprinter(key);
16508
+ if (fingerprint !== void 0) entries.push([key, fingerprint]);
16509
+ }
16510
+ return Object.fromEntries(entries);
16511
+ }
15715
16512
  function maskedPropertyFingerprintsFor(recordedProperties, templateProps) {
15716
16513
  const entries = [];
15717
16514
  for (const key of Object.keys(recordedProperties)) {
@@ -15725,48 +16522,111 @@ function maskedPropertyFingerprintsOf(record) {
15725
16522
  const read = /* @__PURE__ */ new Map();
15726
16523
  if (record === null || typeof record !== "object") return read;
15727
16524
  const field = record.maskedPropertyFingerprints;
15728
- if (field === null || typeof field !== "object" || Array.isArray(field)) return read;
16525
+ if (!isPlainObject$2(field)) return read;
15729
16526
  for (const [key, value] of Object.entries(field)) if (typeof value === "string" && value.startsWith(FINGERPRINT_PREFIX)) read.set(key, value);
15730
16527
  return read;
15731
16528
  }
15732
- function movedMaskedProperties(record, templateProps) {
16529
+ function maskedPropertyInputFingerprintsOf(record) {
16530
+ const read = /* @__PURE__ */ new Map();
16531
+ if (record === null || typeof record !== "object") return read;
16532
+ const field = record.maskedPropertyInputFingerprints;
16533
+ if (!isPlainObject$2(field)) return read;
16534
+ const text = maskedPropertyFingerprintsOf(record);
16535
+ for (const [key, value] of Object.entries(field)) {
16536
+ if (typeof value !== "string" || !value.startsWith(INPUT_FINGERPRINT_PREFIX)) continue;
16537
+ const half = splitInputFingerprint(value).text;
16538
+ if (half !== void 0 && text.get(key) === half) read.set(key, value);
16539
+ }
16540
+ return read;
16541
+ }
16542
+ function boundInputFingerprints(textFingerprints, inputFingerprints) {
16543
+ if (textFingerprints === void 0 || inputFingerprints === void 0) return void 0;
16544
+ const entries = [];
16545
+ for (const [key, text] of Object.entries(textFingerprints)) {
16546
+ if (!text.startsWith(FINGERPRINT_PREFIX) || !Object.hasOwn(inputFingerprints, key)) continue;
16547
+ const input = inputFingerprints[key];
16548
+ if (splitInputFingerprint(input).text === text) entries.push([key, input]);
16549
+ }
16550
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
16551
+ }
16552
+ async function movedMaskedProperties(record, templateProps, fingerprinter, onRebaseline) {
15733
16553
  const recorded = maskedPropertyFingerprintsOf(record);
15734
16554
  if (recorded.size === 0) return [];
15735
16555
  const properties = record.properties;
15736
16556
  if (properties === null || typeof properties !== "object") return [];
16557
+ const inputs = maskedPropertyInputFingerprintsOf(record);
15737
16558
  const moved = [];
15738
16559
  for (const [key, fingerprint] of recorded) {
15739
16560
  if (!Object.hasOwn(templateProps, key) || !Object.hasOwn(properties, key)) continue;
15740
16561
  if (!carriesSecretMask(properties[key])) continue;
15741
- if (maskedPropertyFingerprint(templateProps[key]) !== fingerprint) moved.push(key);
16562
+ if (maskedPropertyFingerprint(templateProps[key]) !== fingerprint) {
16563
+ moved.push(key);
16564
+ continue;
16565
+ }
16566
+ if (fingerprinter === void 0) continue;
16567
+ const bound = inputs.get(key);
16568
+ if (bound === void 0 && onRebaseline === void 0) continue;
16569
+ const now = await fingerprinter(key);
16570
+ if (now === void 0) continue;
16571
+ if (bound !== void 0) {
16572
+ if (splitInputFingerprint(now).input !== splitInputFingerprint(bound).input) moved.push(key);
16573
+ } else onRebaseline(key, now);
15742
16574
  }
15743
16575
  return moved;
15744
16576
  }
16577
+ function withRebaselinedFingerprints(record, fingerprints) {
16578
+ const text = maskedPropertyFingerprintsOf(record);
16579
+ const field = record.maskedPropertyInputFingerprints;
16580
+ const next = isPlainObject$2(field) ? Object.entries(field) : [];
16581
+ let changed = false;
16582
+ for (const [key, value] of Object.entries(fingerprints)) {
16583
+ if (text.get(key) !== splitInputFingerprint(value).text) continue;
16584
+ const at = next.findIndex(([k]) => k === key);
16585
+ if (at >= 0) next[at] = [key, value];
16586
+ else next.push([key, value]);
16587
+ changed = true;
16588
+ }
16589
+ return changed ? {
16590
+ ...record,
16591
+ maskedPropertyInputFingerprints: Object.fromEntries(next)
16592
+ } : record;
16593
+ }
15745
16594
  const writtenFromDeployedTemplate = /* @__PURE__ */ new WeakSet();
15746
16595
  function markWrittenFromDeployedTemplate(bag) {
15747
16596
  writtenFromDeployedTemplate.add(bag);
15748
16597
  return bag;
15749
16598
  }
15750
- function withMaskedPropertyFingerprints(scrubbed, writtenBag, templateProps, secrets, noEchoParameterValues) {
16599
+ function withMaskedPropertyFingerprints(scrubbed, writtenBag, templateProps, secrets, noEchoParameterValues, inputFingerprints) {
15751
16600
  if (templateProps === void 0) return scrubbed;
15752
16601
  const corpora = [secrets, noEchoParameterValues].filter((corpus) => corpus !== void 0);
15753
16602
  const written = writtenBag !== null && typeof writtenBag === "object" && writtenFromDeployedTemplate.has(writtenBag);
15754
- const { maskedPropertyFingerprints: previous, ...rest } = scrubbed;
16603
+ const { maskedPropertyFingerprints: previous, maskedPropertyInputFingerprints: previousInputs, ...rest } = scrubbed;
15755
16604
  let fingerprints;
15756
- if (written) fingerprints = maskedPropertyFingerprintsFor(scrubbed.properties, templateProps);
15757
- else {
15758
- if (previous === void 0 || previous === null || typeof previous !== "object") return scrubbed;
16605
+ let inputs;
16606
+ if (written) {
16607
+ fingerprints = maskedPropertyFingerprintsFor(scrubbed.properties, templateProps);
16608
+ inputs = boundInputFingerprints(fingerprints, inputFingerprints);
16609
+ } else {
16610
+ if (!isPlainObject$2(previous)) return scrubbed;
15759
16611
  if (corpora.length === 0) return scrubbed;
15760
16612
  fingerprints = { ...previous };
16613
+ inputs = isPlainObject$2(previousInputs) ? { ...previousInputs } : void 0;
15761
16614
  }
15762
16615
  if (fingerprints !== void 0 && corpora.length > 0) {
15763
16616
  const refused = Object.keys(fingerprints).filter((key) => Object.hasOwn(templateProps, key) && corpora.some((corpus) => templateCarriesNeedle(templateProps[key], corpus)));
15764
- if (refused.length > 0) fingerprints = Object.fromEntries(Object.entries(fingerprints).map(([key, value]) => [key, refused.includes(key) ? REFUSED_FINGERPRINT : value]));
16617
+ if (refused.length > 0) {
16618
+ fingerprints = Object.fromEntries(Object.entries(fingerprints).map(([key, value]) => [key, refused.includes(key) ? REFUSED_FINGERPRINT : value]));
16619
+ if (inputs !== void 0) {
16620
+ const kept = Object.entries(inputs).filter(([key]) => !refused.includes(key));
16621
+ inputs = kept.length > 0 ? Object.fromEntries(kept) : void 0;
16622
+ }
16623
+ }
15765
16624
  }
15766
- if (!written && JSON.stringify(fingerprints) === JSON.stringify(previous)) return scrubbed;
15767
- return fingerprints === void 0 ? rest : {
16625
+ if (!written && JSON.stringify(fingerprints) === JSON.stringify(previous) && JSON.stringify(inputs) === JSON.stringify(previousInputs)) return scrubbed;
16626
+ return {
15768
16627
  ...rest,
15769
- maskedPropertyFingerprints: fingerprints
16628
+ ...fingerprints !== void 0 && { maskedPropertyFingerprints: fingerprints },
16629
+ ...inputs !== void 0 && { maskedPropertyInputFingerprints: inputs }
15770
16630
  };
15771
16631
  }
15772
16632
  function backfillMaskedPropertyFingerprints(resources, template, noEchoParameterValues) {
@@ -16094,6 +16954,49 @@ const DEPLOY_RESOLVED_REFERENCE_SERVICES = /* @__PURE__ */ new Set([
16094
16954
  "ssm",
16095
16955
  "ssm-secure"
16096
16956
  ]);
16957
+ function sitsInsideResolvableReference(text, start, end) {
16958
+ const OPENING = "{{resolve:";
16959
+ const opening = text.lastIndexOf(OPENING, start);
16960
+ if (opening < 0) return false;
16961
+ const head = text.slice(opening + 10, start);
16962
+ if (head.includes("}}")) return false;
16963
+ const colon = head.indexOf(":");
16964
+ if (colon >= 0 && !DEPLOY_RESOLVED_REFERENCE_SERVICES.has(head.slice(0, colon))) return false;
16965
+ const close = text.indexOf("}}", end);
16966
+ if (close < 0) return false;
16967
+ const nextOpening = text.indexOf(OPENING, end);
16968
+ if (nextOpening >= 0 && nextOpening < close) return false;
16969
+ return !/["\r\n]/.test(text.slice(opening, close));
16970
+ }
16971
+ const KEPT_PLACEHOLDERS = /* @__PURE__ */ new WeakMap();
16972
+ function recordKeptPlaceholder(bag, placeholder, because) {
16973
+ let kept = KEPT_PLACEHOLDERS.get(bag);
16974
+ if (kept === void 0) {
16975
+ kept = /* @__PURE__ */ new Map();
16976
+ KEPT_PLACEHOLDERS.set(bag, kept);
16977
+ }
16978
+ if (!kept.has(placeholder)) kept.set(placeholder, {
16979
+ because,
16980
+ reported: false
16981
+ });
16982
+ }
16983
+ function takeKeptPlaceholdersInsideReferences(bag, text) {
16984
+ const kept = KEPT_PLACEHOLDERS.get(bag);
16985
+ if (kept === void 0) return [];
16986
+ const found = [];
16987
+ for (const [placeholder, entry] of kept) {
16988
+ if (entry.reported) continue;
16989
+ for (let at = text.indexOf(placeholder); at >= 0; at = text.indexOf(placeholder, at + 1)) if (sitsInsideResolvableReference(text, at, at + placeholder.length)) {
16990
+ entry.reported = true;
16991
+ found.push({
16992
+ placeholder,
16993
+ because: entry.because
16994
+ });
16995
+ break;
16996
+ }
16997
+ }
16998
+ return found;
16999
+ }
16097
17000
  function keepsSecretReferenceToken(resolvedName) {
16098
17001
  return dynamicReferenceTokens(resolvedName).some((token) => DEPLOY_RESOLVED_REFERENCE_SERVICES.has(token.slice(10, -2).split(":")[0] ?? ""));
16099
17002
  }
@@ -17880,6 +18783,13 @@ async function resolveTemplateLeafReferences(value, context) {
17880
18783
  return (await this.resolveDynamicReferencesWithLogTwin(value, value, context)).result;
17881
18784
  }
17882
18785
  async function resolveDynamicReferencesWithLogTwin(value, logTwin, context, inherited, persistedText = false) {
18786
+ if (context?.abandonedResolutions !== void 0) {
18787
+ const bag = context.abandonedResolutions;
18788
+ for (const { placeholder, because } of takeKeptPlaceholdersInsideReferences(bag, value)) {
18789
+ const reason = because instanceof Error ? because.message : String(because);
18790
+ bag.push(this.abandonedUnit("placeholder", placeholder, new Error(`Fn::Sub kept the placeholder ${placeholder} (${reason}) inside a {{resolve:...}} reference, so that reference was never resolved`, { cause: because }), context, value));
18791
+ }
18792
+ }
17883
18793
  const pattern = /\{\{resolve:([^}]+)\}\}/g;
17884
18794
  let result = value;
17885
18795
  let twin = logTwin;
@@ -18342,6 +19252,15 @@ function rethrowStructuralSubFailure(varName, error, context) {
18342
19252
  if (!this.subPlaceholderNamesADeclaredTemplateEntity(varName, context)) return;
18343
19253
  throw error;
18344
19254
  }
19255
+ function noteKeptSubPlaceholder(varName, placeholder, because, context) {
19256
+ if (context.abandonedResolutions === void 0) return;
19257
+ const firstDot = varName.indexOf(".");
19258
+ const head = firstDot >= 0 ? varName.slice(0, firstDot) : varName;
19259
+ for (const declared of [context.template?.Resources, context.template?.Parameters]) if (declared !== void 0 && declared !== null && typeof declared === "object") {
19260
+ if (Object.hasOwn(declared, head)) return;
19261
+ }
19262
+ recordKeptPlaceholder(context.abandonedResolutions, placeholder, because);
19263
+ }
18345
19264
  function subListRefusal(subject, value, context) {
18346
19265
  if (!Array.isArray(value)) return void 0;
18347
19266
  const count = `${value.length} item${value.length === 1 ? "" : "s"}`;
@@ -18451,11 +19370,13 @@ async function resolveSub(subArgs, context, source) {
18451
19370
  this.rethrowStructuralSubFailure(varNameStr, getAttError, context);
18452
19371
  this.logger.warn(this.displayMasked(this.subPlaceholderWarning(varNameStr, getAttError), context));
18453
19372
  replacement = match[0];
19373
+ noteKeptSubPlaceholder(varNameStr, match[0], getAttError, context);
18454
19374
  }
18455
19375
  else {
18456
19376
  this.rethrowStructuralSubFailure(varNameStr, refError, context);
18457
19377
  this.logger.warn(this.displayMasked(this.subPlaceholderWarning(varNameStr, refError), context));
18458
19378
  replacement = match[0];
19379
+ noteKeptSubPlaceholder(varNameStr, match[0], refError, context);
18459
19380
  }
18460
19381
  }
18461
19382
  }
@@ -18972,16 +19893,6 @@ function displayLeaf(value, context) {
18972
19893
  return this.displayMasked(this.logTextOfLeaf(value, context), context);
18973
19894
  }
18974
19895
 
18975
- //#endregion
18976
- //#region src/deployment/assumed-conditions.ts
18977
- const assumedConditionNames = /* @__PURE__ */ new WeakMap();
18978
- function recordAssumedConditions(conditions, assumed) {
18979
- assumedConditionNames.set(conditions, assumed);
18980
- }
18981
- function conditionsAssumedFalse(conditions) {
18982
- return assumedConditionNames.get(conditions) ?? /* @__PURE__ */ new Set();
18983
- }
18984
-
18985
19896
  //#endregion
18986
19897
  //#region src/deployment/intrinsic-resolver/params-conditions.ts
18987
19898
  async function resolveParameters(template, userParameters, options) {
@@ -19523,7 +20434,7 @@ var DiffCalculator = class DiffCalculator {
19523
20434
  conditionalReplacementVerdict(resourceType, propertyPath, oldValue, newValue) {
19524
20435
  return this.replacementRules.conditionalReplacementVerdict(resourceType, propertyPath, oldValue, newValue);
19525
20436
  }
19526
- async calculateDiff(currentState, desiredTemplate, resolveFn, canonicalizeProperties, allowedUnsupportedProperties, freshParameters, maskForLog, recreateTargets) {
20437
+ async calculateDiff(currentState, desiredTemplate, resolveFn, canonicalizeProperties, allowedUnsupportedProperties, freshParameters, maskForLog, recreateTargets, maskedInputs) {
19527
20438
  const changes = /* @__PURE__ */ new Map();
19528
20439
  refuseMalformedResourceEntriesForDeploy(currentState, void 0, void 0);
19529
20440
  refuseMalformedResourceProperties(currentState, void 0, void 0);
@@ -19588,7 +20499,10 @@ var DiffCalculator = class DiffCalculator {
19588
20499
  else if (canonicalizeProperties && !this.valuesEqual(desiredPropsForCompare, desiredAfterDrops)) this.logger.debug(`${logicalId} (${desiredResource.Type}): the provider normalizes part of the declared properties before sending them; the comparison uses the normalized form. Nothing is dropped.`);
19589
20500
  const propertyChanges = await this.compareProperties(desiredResource.Type, currentPropsForCompare, desiredPropsForCompare, maskForLog);
19590
20501
  const reported = new Set(propertyChanges.map((pc) => pc.path));
19591
- for (const key of movedMaskedProperties(currentResource, rawDesiredProps)) {
20502
+ const rebaselined = [];
20503
+ const moved = await movedMaskedProperties(currentResource, rawDesiredProps, maskedInputs && inputFingerprinter(rawDesiredProps, maskedInputs.sources), maskedInputs?.rebaselined && ((key, fingerprint) => rebaselined.push([key, fingerprint])));
20504
+ if (rebaselined.length > 0) maskedInputs.rebaselined.set(logicalId, Object.fromEntries(rebaselined));
20505
+ for (const key of moved) {
19592
20506
  if (reported.has(key)) continue;
19593
20507
  if (!Object.hasOwn(currentPropsForCompare, key)) continue;
19594
20508
  if (!Object.hasOwn(desiredPropsForCompare, key)) continue;
@@ -19601,7 +20515,7 @@ var DiffCalculator = class DiffCalculator {
19601
20515
  requiresReplacement: await this.maskedEditRequiresReplacement(desiredResource.Type, key, oldValue, newValue),
19602
20516
  maskedExpressionChanged: true
19603
20517
  });
19604
- this.logger.debug(safeMsg`${logicalId}: ${key} is recorded masked and its template expression changed (go-to-k/cdkd#4451)`);
20518
+ this.logger.debug(safeMsg`${logicalId}: ${key} is recorded masked and its template expression or a resolved input changed (go-to-k/cdkd#4451, go-to-k/cdkd#4543)`);
19605
20519
  }
19606
20520
  const attributeChanges = this.compareAttributes(currentResource, desiredResource);
19607
20521
  if (propertyChanges.length > 0 || attributeChanges.length > 0) {
@@ -20914,7 +21828,7 @@ var CloudControlProvider = class {
20914
21828
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
20915
21829
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
20916
21830
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
20917
- const { ASGProvider } = await import("./asg-provider-BFlmarbF.js");
21831
+ const { ASGProvider } = await import("./asg-provider-m6f7Veu0.js");
20918
21832
  const delegateRegion = ambientRegion();
20919
21833
  let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
20920
21834
  if (asgProvider === void 0) {
@@ -21020,7 +21934,7 @@ var CloudControlProvider = class {
21020
21934
  const family = SDK_DELETE_FAMILIES.get(resourceType);
21021
21935
  const cached = this.sdkDeleteDelegates.get(family);
21022
21936
  if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
21023
- const provider = family === "rds" ? new (await (import("./rds-provider-DqHELwjV.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-CHnIs1hG.js"))).NeptuneProvider({ region: ccRegion });
21937
+ const provider = family === "rds" ? new (await (import("./rds-provider-DAe7XFvF.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-B_OxkCXj.js"))).NeptuneProvider({ region: ccRegion });
21024
21938
  this.sdkDeleteDelegates.set(family, {
21025
21939
  region: ccRegion,
21026
21940
  provider
@@ -25798,6 +26712,18 @@ function deploymentEventsIndexKey(prefix, stackName, region) {
25798
26712
  function deploymentsDirPrefix(prefix, stackName, region) {
25799
26713
  return `${prefix}/${stackName}/${region}/deployments/`;
25800
26714
  }
26715
+ const DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION = "deployment-event streams and their index, whose recorded error messages can quote values the secret mask does not catch";
26716
+ async function deleteAndPurgeEventObjects(backend, keys, dirPrefix) {
26717
+ if (keys.length === 0) return;
26718
+ try {
26719
+ await backend.deleteRawObjects(keys);
26720
+ } finally {
26721
+ await backend.purgeNoncurrentVersions(keys, {
26722
+ ...keys.length > 1 && { listPrefix: dirPrefix },
26723
+ objectDescription: DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION
26724
+ });
26725
+ }
26726
+ }
25801
26727
  function runIdTimestampMs(runId) {
25802
26728
  const m = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})Z/.exec(runId);
25803
26729
  if (!m) return null;
@@ -25942,7 +26868,7 @@ var DeploymentEventsStore = class {
25942
26868
  return runId !== null && runId < cutoff;
25943
26869
  });
25944
26870
  if (stale.length === 0) return;
25945
- await this.backend.deleteRawObjects(stale);
26871
+ await deleteAndPurgeEventObjects(this.backend, stale, dirPrefix);
25946
26872
  this.logger.debug(`Pruned ${stale.length} superseded deployment-event stream(s) for ${this.stackName} (${this.region})`);
25947
26873
  }
25948
26874
  warnOnce(message) {
@@ -26034,7 +26960,7 @@ var DeploymentEventsReader = class {
26034
26960
  const indexExisted = keys.includes(indexKey);
26035
26961
  if (opts.all === true) {
26036
26962
  const toDelete = runIdsDesc.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
26037
- await this.backend.deleteRawObjects([...toDelete, indexKey]);
26963
+ await deleteAndPurgeEventObjects(this.backend, [...toDelete, indexKey], dirPrefix);
26038
26964
  return {
26039
26965
  deletedRunIds: runIdsDesc,
26040
26966
  remainingRunIds: [],
@@ -26060,35 +26986,39 @@ var DeploymentEventsReader = class {
26060
26986
  const deletedSet = new Set(candidates);
26061
26987
  const deleteKeys = candidates.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
26062
26988
  const remainingRunIds = runIdsDesc.filter((id) => !deletedSet.has(id));
26063
- const indexDeleted = await this.rewriteIndexAfterPrune(indexKey, stackName, region, deletedSet, remainingRunIds.length === 0, indexExisted);
26064
- await this.backend.deleteRawObjects(deleteKeys);
26989
+ if (remainingRunIds.length === 0) {
26990
+ await deleteAndPurgeEventObjects(this.backend, [...deleteKeys, indexKey], dirPrefix);
26991
+ return {
26992
+ deletedRunIds: candidates,
26993
+ remainingRunIds,
26994
+ indexDeleted: indexExisted
26995
+ };
26996
+ }
26997
+ await this.rewriteIndexAfterPrune(indexKey, stackName, region, deletedSet);
26998
+ await deleteAndPurgeEventObjects(this.backend, deleteKeys, dirPrefix);
26065
26999
  return {
26066
27000
  deletedRunIds: candidates,
26067
27001
  remainingRunIds,
26068
- indexDeleted
27002
+ indexDeleted: false
26069
27003
  };
26070
27004
  }
26071
- async rewriteIndexAfterPrune(indexKey, stackName, region, deletedRunIds, noRunsRemain, indexExisted) {
26072
- if (noRunsRemain) {
26073
- await this.backend.deleteRawObjects([indexKey]);
26074
- return indexExisted;
26075
- }
27005
+ async rewriteIndexAfterPrune(indexKey, stackName, region, deletedRunIds) {
26076
27006
  let raw;
26077
27007
  try {
26078
27008
  raw = await this.backend.getRawObject(indexKey);
26079
27009
  } catch {
26080
- return false;
27010
+ return;
26081
27011
  }
26082
- if (raw === null) return false;
27012
+ if (raw === null) return;
26083
27013
  let parsed;
26084
27014
  try {
26085
27015
  parsed = JSON.parse(raw);
26086
27016
  } catch {
26087
- return false;
27017
+ return;
26088
27018
  }
26089
- if (!Array.isArray(parsed.runs)) return false;
27019
+ if (!Array.isArray(parsed.runs)) return;
26090
27020
  const remaining = parsed.runs.filter((r) => !deletedRunIds.has(r.runId));
26091
- if (remaining.length === parsed.runs.length) return false;
27021
+ if (remaining.length === parsed.runs.length) return;
26092
27022
  const file = {
26093
27023
  indexVersion: 1,
26094
27024
  stackName,
@@ -26097,7 +27027,6 @@ var DeploymentEventsReader = class {
26097
27027
  lastModified: Date.now()
26098
27028
  };
26099
27029
  await this.backend.putRawObject(indexKey, JSON.stringify(file, null, 2));
26100
- return false;
26101
27030
  }
26102
27031
  };
26103
27032
 
@@ -26468,11 +27397,25 @@ const nonEmptyString = (v) => typeof v === "string" && v.length > 0;
26468
27397
 
26469
27398
  //#endregion
26470
27399
  //#region src/deployment/rollback-executor/messages.ts
26471
- function throwIfDeleteSkipped(result, logicalId, physicalId, duringClause) {
27400
+ function throwIfDeleteSkipped(result, logicalId, physicalId, duringClause, guardScope) {
27401
+ recordRollbackDeleteGuards(result, logicalId, physicalId, guardScope);
26472
27402
  const reason = deleteSkipReason(result);
26473
27403
  if (reason === void 0) return;
26474
27404
  throw new Error(deleteSkippedMessage(logicalId, physicalId, reason, duringClause));
26475
27405
  }
27406
+ function recordRollbackDeleteGuards(result, logicalId, physicalId, scope) {
27407
+ for (const guard of deleteIndeterminateGuards(result)) scope.ctx.recordEvent?.({
27408
+ eventType: "RESOURCE_GUARD_INDETERMINATE",
27409
+ stackName: scope.stackName,
27410
+ operation: "DELETE",
27411
+ logicalId,
27412
+ resourceType: scope.resourceType,
27413
+ ...scope.provisionedBy && { provisionedBy: scope.provisionedBy },
27414
+ ...physicalId && { physicalId: scope.mask(physicalId) },
27415
+ guard: guard.guard,
27416
+ reason: scope.mask(guard.reason)
27417
+ });
27418
+ }
26476
27419
  const SKIP_FINAL_SNAPSHOT_FLAG = "--skip-final-snapshot";
26477
27420
  const REPLAYING_STATE_CREATE_CONTEXT = { replayingState: true };
26478
27421
  function replayingStateCreateContext(secrets) {
@@ -27093,7 +28036,7 @@ function classifyFailedOp(op, stateResources) {
27093
28036
  if (op.changeType === "CREATE") {
27094
28037
  if (!op.physicalId) return "skip-failed-unknown";
27095
28038
  if (!current) return "skip-failed-noop";
27096
- if (current.physicalId !== op.physicalId) return "skip-failed-noop";
28039
+ if (current.physicalId !== op.physicalId) return "skip-failed-mismatch";
27097
28040
  const policy = effectiveDeletionPolicy(current.resourceType, current.deletionPolicy, current.properties);
27098
28041
  if (policy === "Retain") return "orphan-failed-create-retain";
27099
28042
  if (policy === "Snapshot") return "delete-failed-create-with-final-snapshot";
@@ -27357,7 +28300,7 @@ async function replayDelete(s) {
27357
28300
  let finalSnapshotIdentifier;
27358
28301
  if (takeFinalSnapshot) finalSnapshotIdentifier = await prepareCreateRollbackFinalSnapshot(op, deleteProvisionedBy, ctx, mask);
27359
28302
  logger.info(` Rollback: Deleting created resource ${safe(op.logicalId)} (${safe(op.resourceType)})` + (takeFinalSnapshot ? " — DeletionPolicy: Snapshot" : "") + (snapshotPolicy && !takeFinalSnapshot ? " — DeletionPolicy: Snapshot NOT taken (--skip-final-snapshot)" : ""));
27360
- const { provider } = ctx.providerRegistry.getProviderFor({
28303
+ const { provider, provisionedBy: deleteRoutedVia } = ctx.providerRegistry.getProviderFor({
27361
28304
  resourceType: op.resourceType,
27362
28305
  provisionedBy: deleteProvisionedBy
27363
28306
  });
@@ -27370,7 +28313,13 @@ async function replayDelete(s) {
27370
28313
  deletionPolicy: snapshotPolicy ? "Snapshot" : "Delete",
27371
28314
  recordedAttributes: stateResources[op.logicalId]?.attributes
27372
28315
  });
27373
- throwIfDeleteSkipped(createRollbackDelete, op.logicalId, op.physicalId, "while rolling back its CREATE");
28316
+ throwIfDeleteSkipped(createRollbackDelete, op.logicalId, op.physicalId, "while rolling back its CREATE", {
28317
+ ctx,
28318
+ stackName,
28319
+ resourceType: op.resourceType,
28320
+ provisionedBy: deleteRoutedVia,
28321
+ mask
28322
+ });
27374
28323
  delete stateResources[op.logicalId];
27375
28324
  logger.info(` Rollback: ${safe(op.logicalId)} deleted successfully`);
27376
28325
  await afterOp?.(op.logicalId);
@@ -27398,7 +28347,7 @@ async function replayReadopt(s) {
27398
28347
  survivorReason = survivorMessages.reason;
27399
28348
  result.warnings++;
27400
28349
  } else {
27401
- const { provider: newDeleteProvider } = ctx.providerRegistry.getProviderFor({
28350
+ const { provider: newDeleteProvider, provisionedBy: newDeleteVia } = ctx.providerRegistry.getProviderFor({
27402
28351
  resourceType: op.resourceType,
27403
28352
  provisionedBy: current.provisionedBy ?? op.provisionedBy
27404
28353
  });
@@ -27411,7 +28360,13 @@ async function replayReadopt(s) {
27411
28360
  deletionPolicy: replacementDeletePolicy(current.updateReplacePolicy),
27412
28361
  recordedAttributes: current.attributes
27413
28362
  });
27414
- throwIfDeleteSkipped(readoptDelete, op.logicalId, current.physicalId, "while reversing its replacement (re-adopting the retained old resource)");
28363
+ throwIfDeleteSkipped(readoptDelete, op.logicalId, current.physicalId, "while reversing its replacement (re-adopting the retained old resource)", {
28364
+ ctx,
28365
+ stackName,
28366
+ resourceType: op.resourceType,
28367
+ provisionedBy: newDeleteVia,
28368
+ mask
28369
+ });
27415
28370
  }
27416
28371
  stateResources[op.logicalId] = prev;
27417
28372
  logger.info(` Rollback: ${safe(op.logicalId)} restored to the retained old resource`);
@@ -27556,10 +28511,17 @@ async function replayReverseReplacement(s) {
27556
28511
  physicalId: prev.physicalId,
27557
28512
  via: createProvisionedBy
27558
28513
  }, logger, mask, true);
27559
- const resolveNewDeleteProvider = () => ctx.providerRegistry.getProviderFor({
28514
+ const resolveNewDeleteRoute = () => ctx.providerRegistry.getProviderFor({
27560
28515
  resourceType: op.resourceType,
27561
28516
  provisionedBy: current.provisionedBy ?? op.provisionedBy
27562
- }).provider;
28517
+ });
28518
+ const newDeleteGuardScope = (provisionedBy) => ({
28519
+ ctx,
28520
+ stackName,
28521
+ resourceType: op.resourceType,
28522
+ provisionedBy,
28523
+ mask
28524
+ });
27563
28525
  const newCopyClaimed = inlinePolicyWriters.claimedFor(op.resourceType, op.logicalId, stateResources);
27564
28526
  let deletedNewFirst = false;
27565
28527
  let createResult;
@@ -27597,13 +28559,14 @@ async function replayReverseReplacement(s) {
27597
28559
  logger.info(` Rollback: re-create collided with the new resource's name — deleting the new resource (${displaySafe(mask(current.physicalId))}) first...` + (typeChanged ? ` (this op changed the resource's Type, ${safe(op.resourceType)} -> ${safe(oldType)}, which share a name space)` : ""));
27598
28560
  {
27599
28561
  const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
27600
- const deleteNewFirst = await resolveNewDeleteProvider().delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
28562
+ const deleteNewFirstRoute = resolveNewDeleteRoute();
28563
+ const deleteNewFirst = await deleteNewFirstRoute.provider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
27601
28564
  expectedRegion: ctx.region,
27602
28565
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier },
27603
28566
  deletionPolicy: replacementDeletePolicy(current.updateReplacePolicy),
27604
28567
  recordedAttributes: current.attributes
27605
28568
  });
27606
- throwIfDeleteSkipped(deleteNewFirst, op.logicalId, current.physicalId, "while clearing the new resource so the old one could be re-created");
28569
+ throwIfDeleteSkipped(deleteNewFirst, op.logicalId, current.physicalId, "while clearing the new resource so the old one could be re-created", newDeleteGuardScope(deleteNewFirstRoute.provisionedBy));
27607
28570
  }
27608
28571
  deletedNewFirst = true;
27609
28572
  delete stateResources[op.logicalId];
@@ -27662,14 +28625,15 @@ async function replayReverseReplacement(s) {
27662
28625
  await noteRetainedResource(op.resourceType, op.logicalId);
27663
28626
  } else if (!deletedNewFirst && !adoptedLiveNewResource) try {
27664
28627
  const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
27665
- const deleteNewAfterRecreate = await resolveNewDeleteProvider().delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
28628
+ const deleteNewAfterRecreateRoute = resolveNewDeleteRoute();
28629
+ const deleteNewAfterRecreate = await deleteNewAfterRecreateRoute.provider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
27666
28630
  expectedRegion: ctx.region,
27667
28631
  ...newCopyClaimed && { inlinePolicyClaimed: newCopyClaimed },
27668
28632
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier },
27669
28633
  deletionPolicy: replacementDeletePolicy(current.updateReplacePolicy),
27670
28634
  recordedAttributes: current.attributes
27671
28635
  });
27672
- throwIfDeleteSkipped(deleteNewAfterRecreate, op.logicalId, current.physicalId, "while deleting the new resource after re-creating the old one");
28636
+ throwIfDeleteSkipped(deleteNewAfterRecreate, op.logicalId, current.physicalId, "while deleting the new resource after re-creating the old one", newDeleteGuardScope(deleteNewAfterRecreateRoute.provisionedBy));
27673
28637
  } catch (deleteError) {
27674
28638
  logger.warn(mask(` Rollback: old ${safe(op.logicalId)} re-created, but deleting the new resource (${displaySafe(mask(current.physicalId))}) failed: ${displaySafe(deleteError instanceof Error ? deleteError.message : String(deleteError))}. Delete it manually — it is no longer tracked in state.`));
27675
28639
  survivorReason = `The replacement's new ${op.resourceType} (${current.physicalId}) could not be deleted after the old resource was re-created: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}. It is live, still billing, and no longer tracked by cdkd — delete it yourself.`;
@@ -27910,6 +28874,10 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
27910
28874
  case "skip-failed-noop":
27911
28875
  logger.info(` Rollback: failed ${safe(op.changeType)} of ${safe(op.logicalId)} (${safe(op.resourceType)}) left nothing to revert, skipping`);
27912
28876
  break;
28877
+ case "skip-failed-mismatch":
28878
+ logger.warn(safeMsg` Rollback: Skipping failed CREATE of ${shownLogicalId(op.logicalId)} (${refusalResourceType(op.resourceType)}) — it recorded ${mask(String(op.physicalId))}, which is not the resource state tracks under this id; manual attention may be required`);
28879
+ recordRollbackSkip(skipScope, op, "The failed CREATE recorded a physical id other than the one state now tracks under this logical id, so the rollback left it as it is; manual attention may be required.");
28880
+ break;
27913
28881
  case "skip-failed-unknown":
27914
28882
  logger.warn(` Rollback: failed CREATE of ${safe(op.logicalId)} (${safe(op.resourceType)}) recorded no physical id — if it was partially created in AWS, delete it manually`);
27915
28883
  recordRollbackSkip(skipScope, op, "The failed CREATE recorded no physical id, so the rollback cannot address it; if it was partially created in AWS, delete it manually.");
@@ -27958,7 +28926,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
27958
28926
  let finalSnapshotIdentifier;
27959
28927
  if (takeFinalSnapshot) finalSnapshotIdentifier = await prepareCreateRollbackFinalSnapshot(op, deleteProvisionedBy, ctx, mask);
27960
28928
  logger.info(` Rollback: deleting partially-created ${safe(op.logicalId)} (${safe(op.resourceType)}) (--revert-failed)` + (takeFinalSnapshot ? " — DeletionPolicy: Snapshot" : "") + (snapshotPolicy && !takeFinalSnapshot ? " — DeletionPolicy: Snapshot NOT taken (--skip-final-snapshot)" : ""));
27961
- const { provider } = ctx.providerRegistry.getProviderFor({
28929
+ const { provider, provisionedBy: deleteRoutedVia } = ctx.providerRegistry.getProviderFor({
27962
28930
  resourceType: op.resourceType,
27963
28931
  provisionedBy: deleteProvisionedBy
27964
28932
  });
@@ -27971,7 +28939,13 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
27971
28939
  deletionPolicy: snapshotPolicy ? "Snapshot" : "Delete",
27972
28940
  recordedAttributes: stateResources[op.logicalId]?.attributes
27973
28941
  });
27974
- throwIfDeleteSkipped(failedCreateDelete, op.logicalId, op.physicalId, "while deleting the partially-created resource (--revert-failed)");
28942
+ throwIfDeleteSkipped(failedCreateDelete, op.logicalId, op.physicalId, "while deleting the partially-created resource (--revert-failed)", {
28943
+ ctx,
28944
+ stackName,
28945
+ resourceType: op.resourceType,
28946
+ provisionedBy: deleteRoutedVia,
28947
+ mask
28948
+ });
27975
28949
  delete stateResources[op.logicalId];
27976
28950
  await options.afterOp?.(op.logicalId);
27977
28951
  ctx.recordEvent?.({
@@ -28072,7 +29046,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
28072
29046
  error: maskedRollbackEventError(revertError, mask)
28073
29047
  });
28074
29048
  }
28075
- inlinePolicyWriters.noteOutcome(op, action === "skip-failed-noop" || ownRecord(stateResources, op.logicalId) !== recordBefore);
29049
+ inlinePolicyWriters.noteOutcome(op, action === "skip-failed-noop" || action === "skip-failed-mismatch" || ownRecord(stateResources, op.logicalId) !== recordBefore);
28076
29050
  }
28077
29051
  if (result.interrupted) await restoreHeldInlinePolicies(inlinePolicyWriters, stateResources, stackName, ctx, result, { refuseAll: true });
28078
29052
  if (emitEnvelope) ctx.recordEvent?.({
@@ -28091,22 +29065,22 @@ async function replayFailedOperations(...args) {
28091
29065
 
28092
29066
  //#endregion
28093
29067
  //#region src/provisioning/nested-stack-context.ts
28094
- const storage = new AsyncLocalStorage();
29068
+ const storage$1 = new AsyncLocalStorage();
28095
29069
  function withNestedStackContext(ctx, fn) {
28096
- return storage.run(ctx, fn);
29070
+ return storage$1.run(ctx, fn);
28097
29071
  }
28098
29072
  function getCurrentNestedStackContext() {
28099
- return storage.getStore();
29073
+ return storage$1.getStore();
28100
29074
  }
28101
29075
  async function collectNestedChildUnaddressed(fn) {
28102
- const ctx = storage.getStore();
29076
+ const ctx = storage$1.getStore();
28103
29077
  if (!ctx) return {
28104
29078
  value: await fn(),
28105
29079
  unaddressed: void 0
28106
29080
  };
28107
29081
  const slot = {};
28108
29082
  return {
28109
- value: await storage.run({
29083
+ value: await storage$1.run({
28110
29084
  ...ctx,
28111
29085
  childUnaddressed: slot
28112
29086
  }, fn),
@@ -28117,7 +29091,7 @@ async function collectNestedChildUnaddressed(fn) {
28117
29091
  //#endregion
28118
29092
  //#region src/deployment/nested-child-journal.ts
28119
29093
  const NESTED_PENDING_PARENT_REASON = "nested-pending-parent";
28120
- const NESTED_STACK_TYPE = "AWS::CloudFormation::Stack";
29094
+ const NESTED_STACK_TYPE$1 = "AWS::CloudFormation::Stack";
28121
29095
  const MAX_NESTED_WALK_DEPTH = 32;
28122
29096
  function nestedChildStackName(parentStackName, logicalId) {
28123
29097
  return `${parentStackName}~${logicalId}`;
@@ -28134,8 +29108,46 @@ function nestedPendingSnapshot(state) {
28134
29108
  }
28135
29109
  };
28136
29110
  }
29111
+ function displacedPhysicalIdShown(op, logger, physicalId = journalOpPhysicalId(op)) {
29112
+ if (physicalId === void 0) return void 0;
29113
+ const masker = createOpMasker(logger, /* @__PURE__ */ new Map());
29114
+ for (const properties of [
29115
+ op.properties,
29116
+ op.attemptedProperties,
29117
+ op.previousState?.properties
29118
+ ]) {
29119
+ if (properties === void 0) continue;
29120
+ masker.addNamed({
29121
+ resourceType: op.resourceType,
29122
+ properties,
29123
+ logicalId: op.logicalId,
29124
+ physicalIds: [physicalId]
29125
+ });
29126
+ }
29127
+ return displaySafe(String(masker.mask(physicalId)));
29128
+ }
29129
+ function displacedOpClause(op, marks, logger) {
29130
+ const retainedOld = retainedOldPhysicalId(op);
29131
+ if (retainedOld !== void 0 && marks.some((m) => isMarkFor(m, op))) {
29132
+ const shownOld = displacedPhysicalIdShown(op, logger, retainedOld);
29133
+ return `replaced ${shownOld} ${op.oldResourceRetained === true ? "but kept it (UpdateReplacePolicy: Retain)" : "and may have kept it (the journal records no verdict)"}; cdkd import adopted the replacement, so ${shownOld} is left untracked`;
29134
+ }
29135
+ const shownId = displacedPhysicalIdShown(op, logger);
29136
+ return shownId !== void 0 ? `recorded ${shownId}, which cdkd import has since replaced under this id` : "recorded no physical id, and cdkd import has since put another resource under this id";
29137
+ }
29138
+ function recordDisplacedSkips(recordEvent, stackName, ops) {
29139
+ for (const op of ops) recordEvent?.({
29140
+ eventType: "ROLLBACK_RESOURCE_SKIPPED",
29141
+ stackName,
29142
+ operation: op.changeType,
29143
+ logicalId: op.logicalId,
29144
+ resourceType: op.resourceType,
29145
+ ...op.provisionedBy && { provisionedBy: op.provisionedBy },
29146
+ reason: "cdkd import has since put another resource under this logical id, so the op was not reverted; check the resource it recorded by hand"
29147
+ });
29148
+ }
28137
29149
  function revertedNestedRowIds(ops) {
28138
- return ops.filter((op) => op.resourceType === NESTED_STACK_TYPE && op.changeType === "UPDATE").map((op) => op.logicalId);
29150
+ return ops.filter((op) => op.resourceType === NESTED_STACK_TYPE$1 && op.changeType === "UPDATE").map((op) => op.logicalId);
28139
29151
  }
28140
29152
  const revertRunStorage = new AsyncLocalStorage();
28141
29153
  function withNestedRevertRun(runId, fn) {
@@ -28161,7 +29173,7 @@ async function dropNestedChildJournals(args) {
28161
29173
  if (!isPlainRecord(resources)) return;
28162
29174
  if (depthExceeded(depth, parentStackName, logger)) return;
28163
29175
  for (const [logicalId, record] of Object.entries(resources)) {
28164
- if (!isPlainRecord(record) || record["resourceType"] !== NESTED_STACK_TYPE) continue;
29176
+ if (!isPlainRecord(record) || record["resourceType"] !== NESTED_STACK_TYPE$1) continue;
28165
29177
  const child = nestedChildStackName(parentStackName, logicalId);
28166
29178
  try {
28167
29179
  const data = await stateBackend.getState(child, region);
@@ -28319,8 +29331,9 @@ async function revertNestedChildFromJournal(args) {
28319
29331
  for (let s = segments.length - 1; s >= 0; s--) {
28320
29332
  const segment = segments[s];
28321
29333
  const skipPrefix = segment.skipPrefix ?? getCurrentSkipPrefix();
29334
+ const split = splitImportedOps(segment.operations, segment);
28322
29335
  const result = await withNestedStackContext(childCtx, () => withSkipPrefix(skipPrefix, () => withStackName(childStackName, () => withCreateTokenLedger(ledgerForStack(ctx.stateBackend, childStackName, region), () => withNestedRevertRun(runId, async (inner) => {
28323
- const replayed = await replayRollback(segment.operations, stateResources, childStackName, execCtx, {
29336
+ const replayed = await replayRollback(split.replay, stateResources, childStackName, execCtx, {
28324
29337
  afterOp: save,
28325
29338
  onOrphan: (record) => mintedOrphans.push(record),
28326
29339
  inlinePolicyWriters
@@ -28332,7 +29345,9 @@ async function revertNestedChildFromJournal(args) {
28332
29345
  };
28333
29346
  })))));
28334
29347
  failures += result.failures;
28335
- warnings += result.warnings;
29348
+ warnings += result.warnings + split.displaced.length;
29349
+ recordDisplacedSkips(execCtx.recordEvent, childStackName, split.displaced);
29350
+ for (const op of split.displaced) logger.warn(safeMsg`Nested stack ${childStackName}: ${op.logicalId} ` + safeMsg`${displacedOpClause(op, segment.importedResources ?? [], logger)}; ` + "not reverted, check that resource by hand");
28336
29351
  }
28337
29352
  restoring = failures === 0;
28338
29353
  await save();
@@ -29318,6 +30333,24 @@ const cyan = (s) => `${codes.cyan}${s}${codes.reset}`;
29318
30333
  const gray = (s) => `${codes.gray}${s}${codes.reset}`;
29319
30334
  const bold = (s) => `${codes.bright}${s}${codes.reset}`;
29320
30335
 
30336
+ //#endregion
30337
+ //#region src/deployment/delete-guard-scope.ts
30338
+ const storage = new AsyncLocalStorage();
30339
+ function collectDeleteGuards(sink, fn) {
30340
+ return storage.run(sink, fn);
30341
+ }
30342
+ function reportDeleteGuards(result, target) {
30343
+ const sink = storage.getStore();
30344
+ if (!sink) return;
30345
+ for (const guard of deleteIndeterminateGuards(result)) sink.push({
30346
+ guard: guard.guard,
30347
+ reason: guard.reason,
30348
+ physicalId: target.physicalId,
30349
+ resourceType: target.resourceType,
30350
+ ...target.provisionedBy && { provisionedBy: target.provisionedBy }
30351
+ });
30352
+ }
30353
+
29321
30354
  //#endregion
29322
30355
  //#region src/deployment/deploy-engine/replacement.ts
29323
30356
  function replacementDeleteContext(updateReplacePolicy) {
@@ -29336,7 +30369,7 @@ async function prepareFinalSnapshotForDelete(logicalId, resourceType, currentRes
29336
30369
  }
29337
30370
  throw unsupportedFinalSnapshotError(logicalId, resourceType, "--skip-final-snapshot");
29338
30371
  }
29339
- async function replaceDeleteFirstAndRecreate(logicalId, resourceType, oldResourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, secrets, updateReplacePolicy) {
30372
+ async function replaceDeleteFirstAndRecreate(logicalId, resourceType, oldResourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, secrets, updateReplacePolicy, oldDeleteProvisionedBy) {
29340
30373
  const createContext = { maskSecrets: createSecretMasker(secrets) };
29341
30374
  const finalSnapshotIdentifier = await this.prepareFinalSnapshotForDelete(logicalId, oldResourceType, currentResource, updateReplacePolicy);
29342
30375
  let deleteResult;
@@ -29351,6 +30384,11 @@ async function replaceDeleteFirstAndRecreate(logicalId, resourceType, oldResourc
29351
30384
  } catch (deleteError) {
29352
30385
  throw new Error(maskSecretsInText(`Failed to delete old resource ${logicalId} (${currentResource.physicalId}) during the --replace delete-first fallback: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`, secrets));
29353
30386
  }
30387
+ reportDeleteGuards(deleteResult, {
30388
+ physicalId: currentResource.physicalId,
30389
+ resourceType: oldResourceType,
30390
+ provisionedBy: oldDeleteProvisionedBy
30391
+ });
29354
30392
  const replaceSkipReason = deleteSkipReason(deleteResult);
29355
30393
  if (replaceSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, replaceSkipReason, "during the --replace delete-first fallback"));
29356
30394
  this.logger.info(` ${green("✓")} Old resource deleted`);
@@ -29455,10 +30493,10 @@ async function createFirstThenDeleteOld(input) {
29455
30493
  if (input.equalIdIsSameResource && createResult.physicalId === currentResource.physicalId) throw markNonRetryable(new CdkdError(maskName(`${displaySafe(logicalId)} (${displaySafe(resourceType)}) requires replacement (${input.trigger}) under a new name, but the create returned the resource being replaced (${displaySafe(currentResource.physicalId)}) instead of a new one, so cdkd cannot tell which name it holds. Nothing was deleted. Delete that resource by hand if it is yours, then re-run the deploy.`), "NAMED_REPLACEMENT_IDEMPOTENT_CREATE"));
29456
30494
  if (retainOld) return createResult;
29457
30495
  this.logger.info(safeMsg` Deleting old ${logicalId} (${currentResource.physicalId})...`);
29458
- await this.deleteReplacedAfterCreate(logicalId, input.oldResourceType, currentResource, input.deleteProvider, input.deleteProperties, finalSnapshotIdentifier, input.deletePolicy, secrets);
30496
+ await this.deleteReplacedAfterCreate(logicalId, input.oldResourceType, currentResource, input.deleteProvider, input.deleteProperties, finalSnapshotIdentifier, input.deletePolicy, secrets, input.deleteProvisionedBy);
29459
30497
  return createResult;
29460
30498
  }
29461
- async function deleteReplacedAfterCreate(logicalId, oldResourceType, currentResource, deleteProvider, deleteProperties, finalSnapshotIdentifier, updateReplacePolicy, secrets) {
30499
+ async function deleteReplacedAfterCreate(logicalId, oldResourceType, currentResource, deleteProvider, deleteProperties, finalSnapshotIdentifier, updateReplacePolicy, secrets, deleteProvisionedBy) {
29462
30500
  let deleteResult = void 0;
29463
30501
  let deleteFailed = false;
29464
30502
  try {
@@ -29474,6 +30512,11 @@ async function deleteReplacedAfterCreate(logicalId, oldResourceType, currentReso
29474
30512
  deleteFailed = true;
29475
30513
  this.logger.warn(safeMsg` ⚠ Failed to delete old resource ${logicalId} (${currentResource.physicalId}): ${deleteMsg}`);
29476
30514
  }
30515
+ reportDeleteGuards(deleteResult, {
30516
+ physicalId: currentResource.physicalId,
30517
+ resourceType: oldResourceType,
30518
+ provisionedBy: deleteProvisionedBy
30519
+ });
29477
30520
  const skipReason = deleteSkipReason(deleteResult);
29478
30521
  if (skipReason !== void 0) this.logger.warn(` ⚠ ${deleteSkippedMessage(logicalId, currentResource.physicalId, skipReason, "while cleaning up the replaced resource", { commandFreeLine: true })}. Delete it manually — it is no longer tracked in state.`);
29479
30522
  else if (!deleteFailed) this.logger.info(` ${green("✓")} Old resource deleted`);
@@ -29737,8 +30780,15 @@ async function provisionCreate(logicalId, change, stateResources, stackName, tem
29737
30780
  const resolvedProps = await this.resolver.resolve(desiredProps, context);
29738
30781
  this.refuseRedactedAttributeReads(logicalId, resourceType, context);
29739
30782
  this.perResourceTemplateProps.set(logicalId, desiredProps);
30783
+ const fingerprintSources = template && this.maskedInputSources(template, stateResources, conditions, stackName);
30784
+ if (fingerprintSources !== void 0) this.perResourceInputFingerprints.set(logicalId, await maskedInputFingerprintsFor(possiblyMaskedKeys(resolvedProps, [
30785
+ context.recordedSecretValues,
30786
+ this.fingerprintNoEchoValues,
30787
+ this.options.inheritedSecrets
30788
+ ]), inputFingerprinter(desiredProps, fingerprintSources)));
29740
30789
  this.perResourceResolvedType.set(logicalId, resourceType);
29741
30790
  const createSecrets = context.recordedSecretValues ?? /* @__PURE__ */ new Map();
30791
+ if (fingerprintSources !== void 0 && resourceType === "AWS::CloudFormation::Stack") recordPassedParameterClasses(createSecrets, await classifyPassedParameters(desiredProps["Parameters"], fingerprintSources));
29742
30792
  recordNestedStackParameterExpressions(createSecrets, resourceType, resolvedProps, desiredProps);
29743
30793
  this.auditResolvedAssetReferences(logicalId, resourceType, resolvedProps);
29744
30794
  this.attemptedResolvedProps.set(logicalId, resolvedProps);
@@ -32630,7 +33680,15 @@ async function provisionUpdate(logicalId, change, stateResources, stackName, tem
32630
33680
  const lostChild = lostCandidate?.mode === "reattach" || lostCandidate !== void 0 && Object.hasOwn(resolvedProps, lostCandidate.property) && Object.hasOwn(currentProps, lostCandidate.property) && keyOrderFreeJson(resolvedProps[lostCandidate.property]) === keyOrderFreeJson(currentProps[lostCandidate.property]) ? lostCandidate : void 0;
32631
33681
  const lostWithParent = lostChild?.mode === "recreate" ? lostChild.parent : void 0;
32632
33682
  const suppliesFreshMaskOnlyValue = carriesFreshNoEchoValue(resolvedProps, updateSecrets);
32633
- const movedMasked = new Set(movedMaskedProperties(currentResource, desiredProps));
33683
+ const fingerprintSources = template && this.maskedInputSources(template, stateResources, conditions, stackName);
33684
+ const fingerprints = fingerprintSources && inputFingerprinter(desiredProps, fingerprintSources);
33685
+ const movedMasked = new Set(await movedMaskedProperties(currentResource, desiredProps, fingerprints));
33686
+ if (fingerprints !== void 0) this.perResourceInputFingerprints.set(logicalId, await maskedInputFingerprintsFor(possiblyMaskedKeys(resolvedProps, [
33687
+ updateSecrets,
33688
+ this.fingerprintNoEchoValues,
33689
+ this.options.inheritedSecrets
33690
+ ]), fingerprints));
33691
+ if (fingerprintSources !== void 0 && resourceType === "AWS::CloudFormation::Stack") recordPassedParameterClasses(updateSecrets, await classifyPassedParameters(desiredProps["Parameters"], fingerprintSources));
32634
33692
  const desiredForSkipCheck = redactSecretsForState(markSameGenerationBag({ ...resolvedProps }), updateSecrets, desiredProps);
32635
33693
  const allowedSilentDrops = this.providerRegistry.getAllowedUnsupportedProperties?.();
32636
33694
  const desiredForSkipCheckAsWritten = currentResource.provisionedBy !== "cc-api" && allowedSilentDrops ? withoutAcceptedSilentDropProperties(resourceType, desiredForSkipCheck, allowedSilentDrops, currentResource.properties) : desiredForSkipCheck;
@@ -32853,10 +33911,11 @@ async function updateByReplacement({ change, counts, currentProps, currentResour
32853
33911
  });
32854
33912
  const replaceProvider = replaceDecision.provider;
32855
33913
  const replaceProps = replaceDecision.provisionedBy === "cc-api" ? this.preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) : resolvedProps;
32856
- const oldDeleteProvider = this.providerRegistry.getProviderFor({
33914
+ const oldDeleteRoute = this.providerRegistry.getProviderFor({
32857
33915
  resourceType: oldResourceType,
32858
33916
  provisionedBy: currentResource.provisionedBy
32859
- }).provider;
33917
+ });
33918
+ const oldDeleteProvider = oldDeleteRoute.provider;
32860
33919
  const equalIdIsSameResource = equalIdNamesSameResource({
32861
33920
  oldType: oldResourceType,
32862
33921
  newType: resourceType,
@@ -32895,6 +33954,7 @@ async function updateByReplacement({ change, counts, currentProps, currentResour
32895
33954
  createProvider: replaceProvider,
32896
33955
  createProps: replaceProps,
32897
33956
  deleteProvider: oldDeleteProvider,
33957
+ deleteProvisionedBy: oldDeleteRoute.provisionedBy,
32898
33958
  deleteProperties: currentResource.properties,
32899
33959
  secrets: updateSecrets,
32900
33960
  change: nameChange,
@@ -32924,6 +33984,11 @@ async function updateByReplacement({ change, counts, currentProps, currentResour
32924
33984
  } catch (deleteError) {
32925
33985
  throw new Error(`Failed to destroy old resource ${logicalId} (${currentResource.physicalId}) during ${recreateFlagName}: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
32926
33986
  }
33987
+ reportDeleteGuards(recreateDeleteResult, {
33988
+ physicalId: currentResource.physicalId,
33989
+ resourceType: oldResourceType,
33990
+ provisionedBy: oldDeleteRoute.provisionedBy
33991
+ });
32927
33992
  const recreateSkipReason = deleteSkipReason(recreateDeleteResult);
32928
33993
  if (recreateSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, recreateSkipReason, `during ${recreateFlagName}`));
32929
33994
  this.logger.info(` ${green("✓")} Old resource deleted`);
@@ -32979,7 +34044,7 @@ async function updateByReplacement({ change, counts, currentProps, currentResour
32979
34044
  if (this.options.replace !== true) throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but the create-first attempt collided with the existing resource: ${createMsg}. ${nameOrigin.descriptor}, so the CloudFormation-style safe replacement order (create the new resource before deleting the old) cannot reuse the occupied name — CloudFormation refuses this shape with "cannot update a stack when a custom-named resource requires replacing". ${nameOrigin.remedy}, or re-run with \`cdkd deploy --replace\` to delete the old resource FIRST and recreate it under the same name (the resource is briefly unavailable while it is recreated).`, "NAMED_REPLACEMENT_COLLISION");
32980
34045
  this.logger.info(` Create-first collided with the existing resource's name and --replace is set — deleting old ${logicalId} (${currentResource.physicalId}) first...`);
32981
34046
  deletedOldFirst = true;
32982
- createResult = await this.replaceDeleteFirstAndRecreate(logicalId, resourceType, oldResourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, updateSecrets, updateReplacePolicy);
34047
+ createResult = await this.replaceDeleteFirstAndRecreate(logicalId, resourceType, oldResourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, updateSecrets, updateReplacePolicy, oldDeleteRoute.provisionedBy);
32983
34048
  }
32984
34049
  if (equalIdIsSameResource && !deletedOldFirst && createResult.physicalId === currentResource.physicalId) {
32985
34050
  const idempotentNameOrigin = this.replacementNameOrigin(logicalId, currentResource.physicalId);
@@ -32987,7 +34052,7 @@ async function updateByReplacement({ change, counts, currentProps, currentResour
32987
34052
  if (this.options.replace !== true) throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but its Create API is name-idempotent: the create-first attempt returned the EXISTING resource (${currentResource.physicalId}) instead of creating a new one, so deleting the "old" resource would silently destroy the resource the deploy just reported as created. ${idempotentNameOrigin.descriptor}; ${idempotentNameOrigin.remedy}, or re-run with \`cdkd deploy --replace\` to delete the old resource FIRST and recreate it under the same name (the resource is briefly unavailable while it is recreated). Note: this branch is also reached when the old resource was deleted out-of-band and the physical id is name-derived — there the create was a genuine fresh create; \`--replace\` converges that case too.`, "NAMED_REPLACEMENT_IDEMPOTENT_CREATE");
32988
34053
  this.logger.info(` Create-first returned the existing resource (name-idempotent Create API) and --replace is set — deleting old ${logicalId} (${currentResource.physicalId}) first...`);
32989
34054
  deletedOldFirst = true;
32990
- createResult = await this.replaceDeleteFirstAndRecreate(logicalId, resourceType, oldResourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, updateSecrets, updateReplacePolicy);
34055
+ createResult = await this.replaceDeleteFirstAndRecreate(logicalId, resourceType, oldResourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, updateSecrets, updateReplacePolicy, oldDeleteRoute.provisionedBy);
32991
34056
  }
32992
34057
  if (deletedOldFirst) {} else if (updateReplacePolicy === "Retain") {
32993
34058
  this.retainedOldOnReplacement.add(logicalId);
@@ -33004,7 +34069,7 @@ async function updateByReplacement({ change, counts, currentProps, currentResour
33004
34069
  snapshotBlockedDelete = true;
33005
34070
  this.logger.warn(` ⚠ Final snapshot for old ${logicalId} (${currentResource.physicalId}) failed: ${snapshotError instanceof Error ? snapshotError.message : String(snapshotError)}. The old resource was NOT deleted (UpdateReplacePolicy: Snapshot) — delete it manually once you have a snapshot; it is no longer tracked in state.`);
33006
34071
  }
33007
- if (!snapshotBlockedDelete) await this.deleteReplacedAfterCreate(logicalId, oldResourceType, currentResource, oldDeleteProvider, currentResource.properties, cleanupFinalSnapshotId, updateReplacePolicy, updateSecrets);
34072
+ if (!snapshotBlockedDelete) await this.deleteReplacedAfterCreate(logicalId, oldResourceType, currentResource, oldDeleteProvider, currentResource.properties, cleanupFinalSnapshotId, updateReplacePolicy, updateSecrets, oldDeleteRoute.provisionedBy);
33008
34073
  }
33009
34074
  }
33010
34075
  this.registerNoEchoAttributes(logicalId, createResult, updateSecrets, resolvedProps);
@@ -33140,6 +34205,11 @@ async function updateInPlace({ conditions, counts, currentProps, currentPropsAsW
33140
34205
  if (!isWaitAbandonedError(deleteError) && !isInterruptedWaitError(deleteError) && !isMarkedNonRetryable(deleteError) && (deleteMsg.includes("does not exist") || deleteMsg.includes("not found") || deleteMsg.includes("NotFound"))) this.logger.debug(`Old resource ${logicalId} already gone, proceeding with CREATE`);
33141
34206
  else throw deleteError;
33142
34207
  }
34208
+ reportDeleteGuards(fallbackDeleteResult, {
34209
+ physicalId: currentResource.physicalId,
34210
+ resourceType,
34211
+ provisionedBy: updateDecision.provisionedBy
34212
+ });
33143
34213
  const fallbackSkipReason = deleteSkipReason(fallbackDeleteResult);
33144
34214
  if (fallbackSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, fallbackSkipReason, "during the UPDATE-not-supported replacement"));
33145
34215
  }
@@ -33154,6 +34224,7 @@ async function updateInPlace({ conditions, counts, currentProps, currentPropsAsW
33154
34224
  createProvider: replProvider,
33155
34225
  createProps: replProps,
33156
34226
  deleteProvider: updateProvider,
34227
+ deleteProvisionedBy: updateDecision.provisionedBy,
33157
34228
  deleteProperties: currentProps,
33158
34229
  secrets: updateSecrets,
33159
34230
  change: fallbackNameChange,
@@ -33283,10 +34354,11 @@ async function provisionDelete(logicalId, change, stateResources, stackName, tem
33283
34354
  }
33284
34355
  const governingPolicy = effectiveDeletionPolicy(resourceType, deletionPolicy, currentResource.properties);
33285
34356
  const finalSnapshotIdentifier = await this.prepareFinalSnapshotForDelete(logicalId, resourceType, currentResource, governingPolicy);
33286
- const deleteProvider = this.providerRegistry.getProviderFor({
34357
+ const deleteRoute = this.providerRegistry.getProviderFor({
33287
34358
  resourceType,
33288
34359
  provisionedBy: currentResource.provisionedBy
33289
- }).provider;
34360
+ });
34361
+ const deleteProvider = deleteRoute.provider;
33290
34362
  this.logger.debug(`Deleting ${logicalId} (${resourceType})`);
33291
34363
  let deleteResult = void 0;
33292
34364
  const inlinePolicyClaimed = this.inlinePolicyClaimedFor(resourceType, logicalId, stateResources);
@@ -33304,6 +34376,11 @@ async function provisionDelete(logicalId, change, stateResources, stackName, tem
33304
34376
  if (!isInterruptedWaitError(deleteError) && !isMarkedNonRetryable(deleteError) && !isWaitAbandonedError(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`);
33305
34377
  else throw deleteError;
33306
34378
  }
34379
+ reportDeleteGuards(deleteResult, {
34380
+ physicalId: currentResource.physicalId,
34381
+ resourceType,
34382
+ provisionedBy: deleteRoute.provisionedBy
34383
+ });
33307
34384
  const deleteSkipped = deleteSkipReason(deleteResult);
33308
34385
  if (deleteSkipped !== void 0) {
33309
34386
  if (progress) progress.current++;
@@ -33426,12 +34503,27 @@ async function provisionResource(logicalId, change, stateResources, stackName, t
33426
34503
  const physicalIdBeforeUpdate = stateResources[logicalId]?.physicalId;
33427
34504
  const provisionedByBeforeUpdate = stateResources[logicalId]?.provisionedBy;
33428
34505
  let nestedChildUnaddressed;
34506
+ const deleteGuards = [];
33429
34507
  try {
33430
34508
  await withResourceDeadline(async () => {
33431
- const { value: bodyResult, unaddressed } = await collectNestedChildUnaddressed(() => this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress));
33432
- deleteSkipped = bodyResult?.deleteSkipped;
33433
- updatePartial = bodyResult?.updatePartial;
33434
- nestedChildUnaddressed = unaddressed;
34509
+ try {
34510
+ const { value: bodyResult, unaddressed } = await collectDeleteGuards(deleteGuards, () => collectNestedChildUnaddressed(() => this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress)));
34511
+ deleteSkipped = bodyResult?.deleteSkipped;
34512
+ updatePartial = bodyResult?.updatePartial;
34513
+ nestedChildUnaddressed = unaddressed;
34514
+ } finally {
34515
+ for (const guard of deleteGuards.splice(0)) this.recordEvent({
34516
+ eventType: "RESOURCE_GUARD_INDETERMINATE",
34517
+ stackName,
34518
+ operation: "DELETE",
34519
+ logicalId,
34520
+ resourceType: guard.resourceType,
34521
+ ...guard.provisionedBy && { provisionedBy: guard.provisionedBy },
34522
+ ...guard.physicalId && { physicalId: this.maskForResource(logicalId, guard.physicalId) },
34523
+ guard: guard.guard,
34524
+ reason: guard.reason
34525
+ });
34526
+ }
33435
34527
  }, {
33436
34528
  warnAfterMs,
33437
34529
  timeoutMs,
@@ -34370,6 +35462,184 @@ function conditionVerdictRecordsEqual(a, b) {
34370
35462
  return names.every((name) => Object.hasOwn(right, name) && left[name].verdict === right[name].verdict && left[name].fingerprint === right[name].fingerprint);
34371
35463
  }
34372
35464
 
35465
+ //#endregion
35466
+ //#region src/utils/nested-template-cycle.ts
35467
+ const NESTED_STACK_TYPE = "AWS::CloudFormation::Stack";
35468
+ function isAbsoluteAssetPath(p) {
35469
+ return path.isAbsolute(p) || p.startsWith("/");
35470
+ }
35471
+ function templateIdentity(templatePath) {
35472
+ const dir = path.dirname(templatePath);
35473
+ let realDir;
35474
+ try {
35475
+ realDir = fs.realpathSync.native(dir);
35476
+ } catch {
35477
+ realDir = path.resolve(dir);
35478
+ }
35479
+ return path.join(realDir, path.basename(templatePath));
35480
+ }
35481
+ function listNestedTemplateRows(template) {
35482
+ if (template === null || typeof template !== "object") return [];
35483
+ const resources = template.Resources;
35484
+ if (resources === null || resources === void 0) return [];
35485
+ const rows = [];
35486
+ for (const [logicalId, resource] of Object.entries(resources)) {
35487
+ const row = resource;
35488
+ if (row?.Type !== NESTED_STACK_TYPE) continue;
35489
+ const assetPath = row.Metadata?.["aws:asset:path"];
35490
+ if (typeof assetPath !== "string" || assetPath.length === 0) continue;
35491
+ rows.push({
35492
+ logicalId,
35493
+ assetPath
35494
+ });
35495
+ }
35496
+ return rows;
35497
+ }
35498
+ function readNestedRows(templatePath) {
35499
+ let parsed;
35500
+ try {
35501
+ parsed = JSON.parse(fs.readFileSync(templatePath, "utf-8"));
35502
+ } catch {
35503
+ return;
35504
+ }
35505
+ return listNestedTemplateRows(parsed);
35506
+ }
35507
+ const MAX_NESTING_DEPTH = 512;
35508
+ const MAX_ROWS_FOLLOWED = 1e4;
35509
+ function findNestedTemplateTreeDefect(nestedTemplates, ancestorTemplatePaths = []) {
35510
+ const onChain = /* @__PURE__ */ new Set();
35511
+ for (const p of ancestorTemplatePaths) onChain.add(templateIdentity(p));
35512
+ const clean = /* @__PURE__ */ new Set();
35513
+ const chain = [];
35514
+ let rowsFollowed = 0;
35515
+ const visit = (logicalId, templatePath) => {
35516
+ if (typeof templatePath !== "string") return void 0;
35517
+ const identity = templateIdentity(templatePath);
35518
+ const lexical = path.resolve(templatePath);
35519
+ chain.push({
35520
+ logicalId,
35521
+ templatePath: identity
35522
+ });
35523
+ try {
35524
+ if (onChain.has(identity)) return {
35525
+ kind: "cycle",
35526
+ chain: [...chain]
35527
+ };
35528
+ if (chain.length > 512) return {
35529
+ kind: "too-deep",
35530
+ chain: [...chain]
35531
+ };
35532
+ if (++rowsFollowed > 1e4) return {
35533
+ kind: "too-large",
35534
+ chain: [...chain]
35535
+ };
35536
+ if (clean.has(lexical)) return void 0;
35537
+ const rows = readNestedRows(templatePath);
35538
+ if (rows === void 0) return void 0;
35539
+ onChain.add(identity);
35540
+ try {
35541
+ const dir = path.dirname(templatePath);
35542
+ for (const row of rows) {
35543
+ if (isAbsoluteAssetPath(row.assetPath)) return {
35544
+ kind: "absolute-path",
35545
+ chain: [...chain],
35546
+ logicalId: row.logicalId,
35547
+ assetPath: row.assetPath
35548
+ };
35549
+ const resolved = resolveAssemblyPath(dir, row.assetPath);
35550
+ if (!resolved.contained) return {
35551
+ kind: "escaping-path",
35552
+ chain: [...chain],
35553
+ logicalId: row.logicalId,
35554
+ assetPath: row.assetPath,
35555
+ escape: resolved,
35556
+ dir
35557
+ };
35558
+ const defect = visit(row.logicalId, resolved.path);
35559
+ if (defect) return defect;
35560
+ }
35561
+ } finally {
35562
+ onChain.delete(identity);
35563
+ }
35564
+ clean.add(lexical);
35565
+ return;
35566
+ } finally {
35567
+ chain.pop();
35568
+ }
35569
+ };
35570
+ for (const [logicalId, templatePath] of Object.entries(nestedTemplates)) {
35571
+ const defect = visit(logicalId, templatePath);
35572
+ if (defect) return defect;
35573
+ }
35574
+ }
35575
+ const MAX_RENDERED_HOPS = 8;
35576
+ function renderChain(chain) {
35577
+ const hop = (h) => `${displayIdent(h.logicalId)} (${displayAssemblyPath(h.templatePath)})`;
35578
+ if (chain.length <= MAX_RENDERED_HOPS) return chain.map(hop).join(" then ");
35579
+ const keep = MAX_RENDERED_HOPS / 2;
35580
+ return [
35581
+ ...chain.slice(0, keep).map(hop),
35582
+ `... ${chain.length - 8} more ...`,
35583
+ ...chain.slice(-4).map(hop)
35584
+ ].join(" then ");
35585
+ }
35586
+ function renderNestedTemplateTreeDefect(defect, stackName, action) {
35587
+ const provenance = `CDK emits an acyclic nested template tree with relative asset paths, so this indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to ${action}.`;
35588
+ const owner = (chain) => {
35589
+ const ids = chain.slice(0, -1).map((h) => h.logicalId);
35590
+ const keep = MAX_RENDERED_HOPS / 2;
35591
+ if (ids.length <= MAX_RENDERED_HOPS) return displayStackName([stackName, ...ids].join("~"));
35592
+ const head = displayStackName([stackName, ...ids.slice(0, keep)].join("~"));
35593
+ const tail = displayStackName(ids.slice(-4).join("~"));
35594
+ return `${head}~...${ids.length - 8} more...~${tail}`;
35595
+ };
35596
+ if (defect.kind === "cycle") {
35597
+ const closing = defect.chain[defect.chain.length - 1];
35598
+ return `The nested template tree under stack ${displayStackName(stackName)} contains a cycle: ${renderChain(defect.chain)}. Nested stack ${displayIdent(closing.logicalId)} (declared in stack ${owner(defect.chain)}) resolves to a template that is already on that nesting chain, so its Metadata['aws:asset:path'] closes a cycle. ${provenance}`;
35599
+ }
35600
+ if (defect.kind === "too-large") return `The nested template tree under stack ${displayStackName(stackName)} has more than ${MAX_ROWS_FOLLOWED} nested-stack rows to follow (the walk stopped at ${renderChain(defect.chain)}). That is far beyond any CDK-generated assembly. Symlinked directories can give one template file many paths, which multiplies the tree without ever repeating on one chain. Refusing to ${action}.`;
35601
+ if (defect.kind === "too-deep") return `The nested template tree under stack ${displayStackName(stackName)} nests more than ${512} levels deep: ${renderChain(defect.chain)}. No tree that deep can deploy, because each level lengthens the child's state key and S3 caps a key at 1024 bytes. ${provenance}`;
35602
+ if (defect.kind === "escaping-path") return `The nested template tree under stack ${displayStackName(stackName)} has nested stack ${displayIdent(defect.logicalId)} (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which ${renderAssemblyPathEscape(defect.escape, defect.dir, action)}`;
35603
+ return `The nested template tree under stack ${displayStackName(stackName)} has nested stack ${displayIdent(defect.logicalId)} (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which is absolute. ${provenance}`;
35604
+ }
35605
+
35606
+ //#endregion
35607
+ //#region src/deployment/nested-output-templates.ts
35608
+ function childTemplateLoader(nestedTemplates) {
35609
+ if (nestedTemplates === void 0) return void 0;
35610
+ const read = /* @__PURE__ */ new Map();
35611
+ const loaderOver = (index) => (logicalId) => {
35612
+ const templatePath = index[logicalId];
35613
+ if (typeof templatePath !== "string") return void 0;
35614
+ const key = path.resolve(templatePath);
35615
+ if (read.has(key)) return read.get(key);
35616
+ let entry;
35617
+ try {
35618
+ const parsed = JSON.parse(fs.readFileSync(templatePath, "utf-8"));
35619
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) entry = {
35620
+ template: parsed,
35621
+ identity: templateIdentity(templatePath),
35622
+ childTemplate: loaderOver(childIndex(parsed, templatePath))
35623
+ };
35624
+ } catch {
35625
+ entry = void 0;
35626
+ }
35627
+ read.set(key, entry);
35628
+ return entry;
35629
+ };
35630
+ return loaderOver(nestedTemplates);
35631
+ }
35632
+ function childIndex(template, templatePath) {
35633
+ const dir = path.dirname(templatePath);
35634
+ const index = Object.create(null);
35635
+ for (const { logicalId, assetPath } of listNestedTemplateRows(template)) {
35636
+ if (isAbsoluteAssetPath(assetPath)) continue;
35637
+ const resolved = resolveAssemblyPath(dir, assetPath);
35638
+ if (resolved.contained) index[logicalId] = resolved.path;
35639
+ }
35640
+ return index;
35641
+ }
35642
+
34373
35643
  //#endregion
34374
35644
  //#region src/deployment/recreate-target-promotion.ts
34375
35645
  function recreateTargetIdsFor(recreateTargets, stackName) {
@@ -34476,6 +35746,14 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
34476
35746
  this.logger.debug(`Resolved ${Object.keys(parameterValues).length} parameters: ${Object.keys(parameterValues).join(", ")}`);
34477
35747
  const backfillNoEchoValues = noEchoParameterValueSeed(template.Parameters, parameterValues, this.options.inheritedSecrets, this.options.parameters);
34478
35748
  this.fingerprintNoEchoValues = backfillNoEchoValues;
35749
+ this.fingerprintParameters = parameterInputsFor({
35750
+ template,
35751
+ values: parameterValues,
35752
+ nestedChild: this.options.parentStackInfo !== void 0,
35753
+ supplied: this.options.parameters,
35754
+ passedClasses: this.options.passedParameterClasses
35755
+ });
35756
+ this.fingerprintChildTemplates = childTemplateLoader(getCurrentNestedStackContext()?.nestedTemplates);
34479
35757
  let maskedFingerprintsBackfilled = backfillMaskedPropertyFingerprints(currentState.resources, template, backfillNoEchoValues) > 0;
34480
35758
  const context = this.buildResolverContext({
34481
35759
  template,
@@ -34527,8 +35805,19 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
34527
35805
  diffResolverContext.bestEffort = true;
34528
35806
  diffResolverContext.skipDynamicReferences = true;
34529
35807
  const diffResolveFn = (value) => this.resolver.resolve(value, diffResolverContext);
34530
- const changes = await this.diffCalculator.calculateDiff(currentState, effectiveTemplate, diffResolveFn, makeCanonicalizePropertiesFn(this.providerRegistry), this.providerRegistry.getAllowedUnsupportedProperties?.(), this.freshNoEchoParameters(parameterValues), this.diffLogMasker(diffResolverContext.recordedSecretValues, effectiveTemplate, parameterValues), recreateTargetIdsFor(this.options.recreateTargets, stackName));
35808
+ const maskedInputSourcesForDiff = this.maskedInputSources(effectiveTemplate, currentState.resources, conditions, stackName);
35809
+ const maskedInputs = maskedInputSourcesForDiff && {
35810
+ sources: maskedInputSourcesForDiff,
35811
+ rebaselined: /* @__PURE__ */ new Map()
35812
+ };
35813
+ const changes = await this.diffCalculator.calculateDiff(currentState, effectiveTemplate, diffResolveFn, makeCanonicalizePropertiesFn(this.providerRegistry), this.providerRegistry.getAllowedUnsupportedProperties?.(), this.freshNoEchoParameters(parameterValues), this.diffLogMasker(diffResolverContext.recordedSecretValues, effectiveTemplate, parameterValues), recreateTargetIdsFor(this.options.recreateTargets, stackName), maskedInputs);
34531
35814
  createOnlyPrefetch.cancel();
35815
+ for (const [logicalId, fingerprints] of maskedInputs?.rebaselined ?? []) {
35816
+ const record = currentState.resources[logicalId];
35817
+ if (record === void 0) continue;
35818
+ currentState.resources[logicalId] = withRebaselinedFingerprints(record, fingerprints);
35819
+ maskedFingerprintsBackfilled = true;
35820
+ }
34532
35821
  const nestedStackTypeChanges = findNestedStackTypeChanges({
34533
35822
  changes,
34534
35823
  stateResources: currentState.resources
@@ -34712,6 +36001,54 @@ function buildResolverContext(base, stackName) {
34712
36001
  ...base.redactedAttributeReads && { redactedAttributeReads: base.redactedAttributeReads }
34713
36002
  };
34714
36003
  }
36004
+ function getAttTargetOf(node) {
36005
+ if (node === null || typeof node !== "object" || Array.isArray(node)) return void 0;
36006
+ const getAtt = node["Fn::GetAtt"];
36007
+ if (Array.isArray(getAtt) && typeof getAtt[0] === "string") return getAtt[0];
36008
+ if (typeof getAtt === "string") return getAtt.split(".")[0];
36009
+ }
36010
+ function maskedInputSources(template, resources, conditions, stackName) {
36011
+ const parameters = this.fingerprintParameters;
36012
+ if (parameters === void 0) return void 0;
36013
+ return {
36014
+ template,
36015
+ parameterInput: parameters.parameterInput,
36016
+ conditions,
36017
+ childTemplate: this.fingerprintChildTemplates,
36018
+ resolve: async (node) => {
36019
+ const { attributeHealer: _healer, ...base } = this.buildResolverContext({
36020
+ template,
36021
+ resources,
36022
+ parameters: parameters.bound,
36023
+ ...conditions && { conditions }
36024
+ }, stackName);
36025
+ const context = {
36026
+ ...base,
36027
+ recordedImports: [],
36028
+ recordedOutputReads: [],
36029
+ bestEffort: true,
36030
+ skipDynamicReferences: true,
36031
+ staleAttributeHeal: { phase: "probe" }
36032
+ };
36033
+ const value = await this.resolver.resolve(structuredClone(node), context);
36034
+ const secrets = context.recordedSecretValues;
36035
+ const target = getAttTargetOf(node);
36036
+ const targetSecrets = target === void 0 ? void 0 : this.perResourceSecrets.get(target);
36037
+ if (targetSecrets !== void 0 && hasMaskableValues(targetSecrets)) {
36038
+ const probe = { value };
36039
+ const redacted = redactSecretsForState(probe, targetSecrets);
36040
+ if (JSON.stringify(redacted) !== JSON.stringify(probe)) return {
36041
+ value,
36042
+ keepAsWritten: true
36043
+ };
36044
+ }
36045
+ return {
36046
+ value,
36047
+ ...secrets && { secrets }
36048
+ };
36049
+ }
36050
+ };
36051
+ }
34715
36052
 
34716
36053
  //#endregion
34717
36054
  //#region src/deployment/label-routing.ts
@@ -34936,6 +36273,9 @@ var DeployEngine = class {
34936
36273
  perResourceTemplateProps = /* @__PURE__ */ new Map();
34937
36274
  perResourceResolvedType = /* @__PURE__ */ new Map();
34938
36275
  fingerprintNoEchoValues = void 0;
36276
+ fingerprintParameters = void 0;
36277
+ fingerprintChildTemplates = void 0;
36278
+ perResourceInputFingerprints = /* @__PURE__ */ new Map();
34939
36279
  outputSecrets = /* @__PURE__ */ new Map();
34940
36280
  outputsPassSecretMaps = [];
34941
36281
  outputsTemplateSource = Object.create(null);
@@ -34984,6 +36324,9 @@ var DeployEngine = class {
34984
36324
  this.perResourceTemplateProps = /* @__PURE__ */ new Map();
34985
36325
  this.perResourceResolvedType = /* @__PURE__ */ new Map();
34986
36326
  this.fingerprintNoEchoValues = void 0;
36327
+ this.fingerprintParameters = void 0;
36328
+ this.fingerprintChildTemplates = void 0;
36329
+ this.perResourceInputFingerprints = /* @__PURE__ */ new Map();
34987
36330
  this.attemptedResolvedProps = /* @__PURE__ */ new Map();
34988
36331
  this.liveTaskLabels = /* @__PURE__ */ new Map();
34989
36332
  this.outputSecrets = /* @__PURE__ */ new Map();
@@ -35011,14 +36354,14 @@ var DeployEngine = class {
35011
36354
  const secrets = this.perResourceSecrets.get(logicalId);
35012
36355
  const templateProps = this.perResourceTemplateProps.get(logicalId);
35013
36356
  const scrubbed = scrubResourceRecord(this.withHealedAttributes(logicalId, record), secrets ?? /* @__PURE__ */ new Map(), templateProps);
35014
- resources[logicalId] = withMaskedPropertyFingerprints(scrubbed, record.properties, templateProps, secrets, this.fingerprintNoEchoValues);
36357
+ resources[logicalId] = withMaskedPropertyFingerprints(scrubbed, record.properties, templateProps, secrets, this.fingerprintNoEchoValues, this.perResourceInputFingerprints.get(logicalId));
35015
36358
  }
35016
36359
  const orphans = state.orphans?.map((entry) => {
35017
36360
  const sameResource = this.perResourceResolvedType.get(entry.logicalId) === entry.state.resourceType;
35018
36361
  const orphanTemplateProps = sameResource ? this.perResourceTemplateProps.get(entry.logicalId) : void 0;
35019
36362
  return {
35020
36363
  ...entry,
35021
- state: withMaskedPropertyFingerprints(scrubResourceRecord(entry.state, (sameResource ? this.perResourceSecrets.get(entry.logicalId) : void 0) ?? /* @__PURE__ */ new Map(), orphanTemplateProps), entry.state.properties, orphanTemplateProps, sameResource ? this.perResourceSecrets.get(entry.logicalId) : void 0, sameResource ? this.fingerprintNoEchoValues : void 0)
36364
+ state: withMaskedPropertyFingerprints(scrubResourceRecord(entry.state, (sameResource ? this.perResourceSecrets.get(entry.logicalId) : void 0) ?? /* @__PURE__ */ new Map(), orphanTemplateProps), entry.state.properties, orphanTemplateProps, sameResource ? this.perResourceSecrets.get(entry.logicalId) : void 0, sameResource ? this.fingerprintNoEchoValues : void 0, sameResource ? this.perResourceInputFingerprints.get(entry.logicalId) : void 0)
35022
36365
  };
35023
36366
  });
35024
36367
  const outputs = this.redactOutputs(state.outputs);
@@ -35134,6 +36477,7 @@ DeployEngine.prototype.recreateDirectionFor = recreateDirectionFor;
35134
36477
  DeployEngine.prototype.peekRoutingForLabel = peekRoutingForLabel;
35135
36478
  DeployEngine.prototype.preparePropertiesForCcApi = preparePropertiesForCcApi;
35136
36479
  DeployEngine.prototype.buildResolverContext = buildResolverContext;
36480
+ DeployEngine.prototype.maskedInputSources = maskedInputSources;
35137
36481
  DeployEngine.prototype.doDeployWithPrefetch = doDeployWithPrefetch;
35138
36482
  DeployEngine.prototype.executeDeployment = executeDeployment;
35139
36483
  DeployEngine.prototype.persistStateAfterOutputFailure = persistStateAfterOutputFailure;
@@ -35191,5 +36535,5 @@ DeployEngine.prototype.replacementNameOrigin = replacementNameOrigin;
35191
36535
  DeployEngine.prototype.orphanedNameCollisionAdvice = orphanedNameCollisionAdvice;
35192
36536
 
35193
36537
  //#endregion
35194
- export { nestedChildStackName as $, hasReadableExportSet as $a, requireConfigObject as $i, s3BucketDomainName as $n, resolveAutoAssetStorage as $o, refuseMalformedOrphanRecordsForDestroy as $r, earliestDefined as $t, ECR_AUTO_DELETE_IMAGES_TAG as A, recoverMaskedOutput as Aa, unwrittenCreateOnlyReplacement as Ai, ec2InstanceProtectionSite as An, describeDockerExecFailure as Ao, malformedDriftResourcePropertiesWarning as Ar, renderAssemblyPathEscape as As, redactedDeleteAddressSkip as At, gray as B, STATE_SOURCED_BASELINE_RULES as Ba, WARM_THROUGHPUT_MEMBERS as Bi, regionLessSecretName as Bn, redactedDockerCause as Bo, malformedOrphansWarning as Br, secretBearingStateKeyWarning as Bt, deleteBudgetKey as C, createSecretMasker as Ca, repairMalformedResourcePropertiesForReadOnly as Ci, UNSPECIFIED_SKIP_REASON as Cn, readBootstrapMarkerBody as Co, deployRefusesOrphanRowsReason as Cr, hasOwnKey as Cs, effectiveDeletionPolicy as Ct, INDEX_SETTLE_POLL_INTERVAL_MS as D, markSameGenerationBag as Da, unreadableResourceEntries as Di, isWaitAbandonedError as Dn, buildDockerImage as Do, hasReadableResources as Dr, absoluteAssemblyPathEscape as Ds, REDACTED_DELETE_ADDRESS_SKIP_REASON as Dt, DELETE_INDEX_WAIT_PROCEED_NOTE as E, maskSecretsInText as Ea, unreadableOrphanRecords as Ei, withIndeterminateGuard as En, buildDenyExternalAccessPolicy as Eo, hasReadableOutputs as Er, ownValue as Es, unsupportedFinalSnapshotError as Et, markRefusedBeforeApplying as F, identityKeyFor as Fa, shownType as Fi, DiffCalculator as Fn, getDockerCmd as Fo, malformedLocalResourcesWarning as Fr, extractDeploymentEventError as Ft, namesAnyDeclaredParameter as G, isSingleDynamicReferenceToken as Ga, coerceCfnBoolean as Gi, isIamRoleArn as Gn, stripControlChars as Go, malformedResourcePropertiesWarning as Gr, collectDeclaredOutputNames as Gt, red as H, STATE_SOURCED_READBACK_RULES as Ha, isWarmThroughputDecrease as Hi, assertFlagRoleArn as Hn, runDockerStreaming as Ho, malformedOutputsWarning as Hr, exportNameSecretExposure as Ht, formatResourceLine as I, carriesSecretMask as Ia, MULTI_REGION_RECREATE_BLOCKED_TYPES as Ii, INTRINSIC_KEYS as In, isDockerClientEnvKey as Io, malformedOrphanRecordsRefusalMessage as Ir, WITHHELD_NAME_DISPLAY as It, makeSiblingClaimReader as J, S3StateBackend as Ja, configIntegerRefusal as Ji, applyCallerIdentityCredentials as Jn, Synthesizer as Jo, malformedStateRefusalMessage as Jr, bindingSkippedOutputs as Jt, reachableDivergentParameters as K, LockManager as Ka, coerceCfnInteger as Ki, sendableAssumeRoleCommand as Kn, AssetManifestLoader as Ko, malformedResourcesWarning as Kr, collectPublishedOutputNames as Kt, createReadOnlyAttributeHealerFactory as L, recordMaskOnlyValue as La, isStatefulRecreateTargetForReplace as Li, IntrinsicFunctionResolver as Ln, isMalformedEnvKey as Lo, malformedOrphanRecordsWarning as Lr, displayTextOrWithheld as Lt, hasCdkAutoDeleteTag as M, dynamicReferenceTokens as Ma, NO_CC_HANDLERS_REASON as Mi, observeThenDisableInstanceApiTermination as Mn, dockerSpawnEnvWithSensitive as Mo, malformedExportSourceWarning as Mr, clearBucketRegionCache as Ms, updatePartialReason as Mt, isTruthyCfnBoolean as N, isUncertifiedBaselineMaskPosition as Na, hasNoCloudControlHandlers as Ni, reDisableInstanceApiTermination as Nn, finchSecretArgvRefusal as No, malformedLocalOutputsWarning as Nr, resolveBucketRegion as Ns, DeploymentEventsReader as Nt, deleteTableWithIndexBusyRetry as O, redactSecretsForState as Oa, findActionableSilentDrops as Oi, markWaitAbandoned as On, resolveDockerContextDirectory as Oo, isReadableOrphanRecord as Or, describeFileReadFailure as Os, isRedactedRecordedValue as Ot, getPriorAttempts as P, pathCrossesDottedKey as Pa, findReplacedReadersOfRecreateTargets as Pi, reEnableInstanceApiTermination as Pn, formatDockerLoginError as Po, malformedLocalResourceEntriesWarning as Pr, DeploymentEventsStore as Pt, getNestedRevertRun as Q, exportNamesCarriedFrom as Qa, requireConfigArray as Qi, s3BucketArn as Qn, resolveApp as Qo, refuseMalformedOrphanRecords as Qr, RollbackInlinePolicyWriters as Qt, bold as R, recordMaskOnlyValuesIn as Ra, isStatefulRecreateTargetSync as Ri, classifyReplaySecretRegion as Rn, partitionSensitiveEnv as Ro, malformedOrphanRowsKeptWarning as Rr, exportAliasCollisionScrubWarning as Rt, compensateRemovedDeletionProtection as S, shareLogOnlyValues as Sa, repairMalformedResourceEntriesForReadOnly as Si, unchangedBehindSecretReference as Sn, parseBootstrapMarker as So, UNREADABLE_RESOURCES_MAP_ROW as Sr, defineOwnKey as Ss, createPreDeleteFinalSnapshot as St, resolveDynamoDbDeleteBudgetMs as T, maskSecretsInError as Ta, unpreviewableOrphanRecords as Ti, deleteSkipReason as Tn, validateContainerRepoName as To, hasReadableOrphans as Tr, nullPrototypeRecord as Ts, refusesFinalSnapshot as Tt, yellow as U, TEMPLATE_SOURCED_RULES as Ua, toCfnInteger as Ui, assertSendableRoleArn as Un, warnFinchArgvExposure as Uo, malformedRenderedContainersWarning as Ur, isWholeDynamicReferenceValue as Ut, green as V, STATE_SOURCED_CROSS_GENERATION_RULES as Va, coerceWarmThroughput as Vi, applyRoleArnIfSet as Vn, runDockerForeground as Vo, malformedOutputsRefusalMessage as Vr, secretSafeKeyDisplay as Vt, computeParameterTaint as W, WHOLE_DYNAMIC_REFERENCE_PATTERN as Wa, toFiniteNumber as Wi, explicitRoleArnOrThrow as Wn, escapeRegExp$2 as Wo, malformedResourceEntriesWarning as Wr, noEchoParameterValueSeed as Wt, NESTED_PENDING_PARENT_REASON as X, acceptedCreateOnlyDropsOf as Xa, readConfigString as Xi, envCredentialsAreAssumedRole as Xn, getDefaultStateBucketName as Xo, refuseDivergentRecordRegionForDestroy as Xr, DEFAULT_RESOURCE_WARN_AFTER_MS as Xt, planOrphanAdoption as Y, rebuildClientForBucketRegion as Ya, configStringRefusal as Yi, callerEnvCredentials as Yn, synthesisStatusMessage as Yo, previewableOrphanRecords as Yr, DEFAULT_RESOURCE_TIMEOUT_MS as Yt, dropSettledNestedJournals as Z, describeRegionValueKind as Za, replayWarn as Zi, isSettledInstanceState as Zn, getLegacyStateBucketName as Zo, refuseMalformedNestedChildOutputs as Zr, maskingRetryLogger as Zt, perType as _, literalSplitDelimitersOf as _a, refuseMalformedResourcesForExport as _i, isCustomResourceType as _n, BOOTSTRAP_MARKER_PREFIX as _o, withSharedDrainBudget as _r, canonicalizeRegion as _s, inheritProducerRegions as _t, conditionInputsFrom as a, markAuxiliaryFailure as aa, refuseMalformedResourceAttributesForOrphan as ai, DBPROXY_TAG_OPTIONS as an, orphansAfterRollback as ao, parameterTypeMayLoseSecretIdentity as ar, stateBucketExistenceConfirmed as as, replayFailedOperations as at, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as b, recordLogOnlyParameterValue as ba, repairMalformedOrphansForReadOnly as bi, slowCcOperationTimeoutMs as bn, getBootstrapMarkerKey as bo, STATE_RESOURCES_MALFORMED as br, StageLoadError as bs, buildFinalSnapshotIdentifier as bt, isSecretBearingReferenceString as c, sameLambdaFunctionAddress as ca, refuseMalformedResourceEntriesForDestroy as ci, refuseMalformedDesiredTags as cn, AssetPublisher as co, carriesDynamicReference as cr, CFN_TEMPLATE_BODY_LIMIT as cs, destroyStackRecordsView as ct, makeCanonicalizePropertiesFn as d, liveMatchesUnresolvedTokenFrame as da, refuseMalformedResourceEntriesForOrphan as di, definedAttributes as dn, WorkGraph as do, keepsSecretReferenceToken as dr, findLargeInlineResources as ds, recordAfterRollbackUpdate as dt, requireConfigString as ea, refuseMalformedOrphans as ei, ledgerForStack as en, hasReasonlessBaselineRefusal as eo, s3BucketDualStackDomainName as er, resolveCaptureObservedState as es, revertNestedChildFromJournal as et, withResourceDeadline as f, inheritNestedStackParameterAssociations as fa, refuseMalformedResourcePropertiesForDrift as fi, stringifyIfAssigned as fn, buildAssetRedirectMap as fo, AWS_NO_VALUE as fr, uploadCfnTemplate as fs, planFailedOps as ft, isProtectionValueActive as g, hasMaskableValues as ga, refuseMalformedResourcesForDestroy as gi, wouldReturnToSdkProvider as gn, AssetModeResolver as go, parseWebACLArn as gr, PARTITION_TABLE as gs, getCurrentProducerRegions as gt, PROTECTION_PROPERTY_BY_TYPE as h, createUnionSecretMasker as ha, refuseMalformedResourcesForDeploy as hi, ccBrokenReason as hn, rewriteTemplateAssetReferences as ho, refStateLookupFromResource as hr, expectedOwnerParam as hs, findNestedStackTypeChanges as ht, conditionFingerprint as i, withRetry as ia, refuseMalformedOutputsForDestroy as ii, DBPROXY_TAGS_WHAT as in, isReadableBag as io, isUnboundTemplateParameter as ir, resolveUseCdkBootstrapAssets as is, withNestedStackContext as it, S3_AUTO_DELETE_OBJECTS_TAG as j, DYNAMIC_REFERENCE_TOKEN_SCAN as ja, withoutSilentDropProperties as ji, isTerminationProtectionPropagationError as jn, describeDockerFailure as jo, malformedExportNamesWarning as jr, resolveAssemblyPath as js, updatePartialMessage as jt, waitForIndexesSettled as k, scrubResourceRecord as ka, findSilentDropProperties as ki, disableInstanceApiTermination as kn, describeDockerCapturedOutput as ko, isReadableResourceEntry as kr, displayAssemblyPath as ks, redactedDeleteAddressFields as kt, keptWholeReasonText as l, DagBuilder as la, refuseMalformedResourceEntriesForImport as li, tagMapAsList as ln, isSensitiveAttributeName as lo, carriesFetchableDynamicReference as lr, CFN_TEMPLATE_URL_LIMIT as ls, getStackRecords as lt, recordedProtectionNote as m, carryLogOnlyValues as ma, refuseMalformedResourcePropertiesForOrphan as mi, ProviderRegistry as mn, loadPublishableAssetManifest as mo, isStalePlaceholderArnAttribute as mr, decodeListingKey as ms, resolveReplacementOldType as mt, IMPLICIT_DELETE_DEPENDENCIES as n, templateResourceTypes as na, refuseMalformedOrphansForOrphan as ni, withCreateTokenLedger as nn, importableOutputKeys as no, s3BucketWebsiteUrl as nr, resolveStateBucketWithDefault as ns, withNestedRevertRun as nt, parentSuppliedValues as o, canonicalLambdaFunctionName as oa, refuseMalformedResourceEntries as oi, planTagDiff as on, orphansCarriedFrom as oo, getAccountInfo as or, warnDeprecatedNoPrefixCliFlag as os, replayRollback as ot, recordedProtectionEvidence as p, recordNestedStackParameterExpressions as pa, refuseMalformedResourcePropertiesForExport as pi, CC_BROKEN_REASON as pn, createAssetRedirectResolver as po, cfnRefValueFromPhysicalId as pr, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as ps, planRollback as pt, resourcesNamingDeclaredParameter as q, isLockInfoExpired as qa, configBooleanRefusal as qi, AWS_CREDENTIAL_ENV_KEYS as qn, getDockerImageBySourceHash as qo, malformedScrubResourceEntriesRefusalMessage as qr, isExportAliasCollision as qt, computeImplicitDeleteEdges as r, describeTypeWithThrottleRetry as ra, refuseMalformedOutputs as ri, acquireIdempotencyToken as rn, importableOutputs as ro, coerceParameterTypedValue as rr, resolveStateBucketWithDefaultAndSource as rs, getCurrentNestedStackContext as rt, readRecordedConditionVerdicts as s, lambdaFunctionNameForMask as sa, refuseMalformedResourceEntriesForDeploy as si, readTagList as sn, shouldRetainResource as so, isImpossibleEmptyStoredAttribute as sr, ssmResolvedValueType as ss, awaitInFlightSibling as st, DeployEngine as t, prefetchCreateOnlyPropertyPaths as ta, refuseMalformedOrphansForDestroy as ti, reserveStackCreateToken as tn, hasUnverifiableParameterRefusal as to, s3BucketRegionalDomainName as tr, resolveSkipPrefix as ts, revertedNestedRowIds as tt, mergeNoChangeOutputs as u, TemplateParser as ua, refuseMalformedResourceEntriesForImportSave as ui, tagPlanWarning as un, stringifyValue as uo, isNamelessDynamicReferenceError as ur, MIGRATE_TMP_PREFIX as us, withStackRecords as ut, readProtection as v, logOnlyValueCount as va, refuseMalformedState as vi, getCurrentResourceSecrets as vn, assertAssetBucketRegion as vo, JSON_LISTING_HOLE_VALUE as vr, derivePartitionAndUrlSuffix as vs, ATOMIC_FINAL_SNAPSHOT_TYPES as vt, resolveDynamoDbDeleteBudgetClock as w, errorCauseChain as wa, repairMalformedResourcesForReadOnly as wi, deleteIndeterminateGuards as wn, validateAssetBucketName as wo, displayLogicalId as wr, hasPlainPrototype$1 as ws, isFinalSnapshotError as wt, beginDeleteWait as x, recordLogOnlyValue as xa, repairMalformedOutputsForReadOnly as xi, ccProtectionRegistryTypes as xn, isCrossRegionRedirect as xo, UNREADABLE_ORPHANS_CONTAINER_ROW as xr, processStackMessages as xs, ccRoutedFinalSnapshotError as xt, DynamoDBGlobalTableProvider as y, printingCorpusOf as ya, repairMalformedOrphanRecordsForReadOnly as yi, CloudControlProvider as yn, ensureAssetStorage as yo, STATE_REGION_DIVERGED as yr, AssemblyReader as ys, PRE_DELETE_SNAPSHOT_TYPES as yt, cyan as z, recordNoEchoAttributeValues as za, renderStatefulReason as zi, producerRegionsFromState as zn, redactDockerArgvValues as zo, malformedOrphansRefusalMessage as zr, secretBearing as zt };
35195
- //# sourceMappingURL=deploy-engine-RCOtmm4V.js.map
36538
+ export { resourcesNamingDeclaredParameter as $, STATE_SOURCED_READBACK_RULES as $a, isWarmThroughputDecrease as $i, explicitRoleArnOrThrow as $n, runDockerForeground as $o, malformedOutputsWarning as $r, noEchoParameterValueSeed as $t, resolveDynamoDbDeleteBudgetClock as A, printingCorpusOf as Aa, repairMalformedOrphanRecordsForReadOnly as Ai, ccProtectionRegistryTypes as An, assertAssetBucketRegion as Ao, STATE_REGION_DIVERGED as Ar, derivePartitionAndUrlSuffix as As, ccRoutedFinalSnapshotError as At, getPriorAttempts as B, scrubResourceRecord as Ba, findSilentDropProperties as Bi, isTerminationProtectionPropagationError as Bn, resolveDockerContextDirectory as Bo, isReadableResourceEntry as Br, describeFileReadFailure as Bs, updatePartialMessage as Bt, perType as C, inheritNestedStackParameterAssociations as Ca, refuseMalformedResourcePropertiesForDrift as Ci, ProviderRegistry as Cn, WorkGraph as Co, isStalePlaceholderArnAttribute as Cr, findLargeInlineResources as Cs, resolveReplacementOldType as Ct, beginDeleteWait as D, hasMaskableValues as Da, refuseMalformedResourcesForDestroy as Di, getCurrentResourceSecrets as Dn, rewriteTemplateAssetReferences as Do, parameterInputsFor as Dr, expectedOwnerParam as Ds, ATOMIC_FINAL_SNAPSHOT_TYPES as Dt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as E, createUnionSecretMasker as Ea, refuseMalformedResourcesForDeploy as Ei, isCustomResourceType as En, loadPublishableAssetManifest as Eo, withSharedDrainBudget as Er, decodeListingKey as Es, inheritProducerRegions as Et, waitForIndexesSettled as F, errorCauseChain as Fa, repairMalformedResourcesForReadOnly as Fi, withIndeterminateGuard as Fn, readBootstrapMarkerBody as Fo, displayLogicalId as Fr, hasOwnKey as Fs, unsupportedFinalSnapshotError as Ft, cyan as G, pathCrossesDottedKey as Ga, findReplacedReadersOfRecreateTargets as Gi, INTRINSIC_KEYS as Gn, finchSecretArgvRefusal as Go, malformedLocalResourceEntriesWarning as Gr, resolveBucketRegion as Gs, WITHHELD_NAME_DISPLAY as Gt, formatResourceLine as H, DYNAMIC_REFERENCE_TOKEN_SCAN as Ha, withoutSilentDropProperties as Hi, reDisableInstanceApiTermination as Hn, describeDockerExecFailure as Ho, malformedExportNamesWarning as Hr, renderAssemblyPathEscape as Hs, DeploymentEventsReader as Ht, ECR_AUTO_DELETE_IMAGES_TAG as I, maskSecretsInError as Ia, unpreviewableOrphanRecords as Ii, isWaitAbandonedError as In, validateAssetBucketName as Io, hasReadableOrphans as Ir, hasPlainPrototype$1 as Is, REDACTED_DELETE_ADDRESS_SKIP_REASON as It, red as J, recordMaskOnlyValue as Ja, isStatefulRecreateTargetForReplace as Ji, producerRegionsFromState as Jn, isDockerClientEnvKey as Jo, malformedOrphanRecordsWarning as Jr, secretBearing as Jt, gray as K, identityKeyFor as Ka, shownType as Ki, IntrinsicFunctionResolver as Kn, formatDockerLoginError as Ko, malformedLocalResourcesWarning as Kr, displayTextOrWithheld as Kt, S3_AUTO_DELETE_OBJECTS_TAG as L, maskSecretsInText as La, unreadableOrphanRecords as Li, markWaitAbandoned as Ln, validateContainerRepoName as Lo, hasReadableOutputs as Lr, nullPrototypeRecord as Ls, isRedactedRecordedValue as Lt, DELETE_INDEX_WAIT_PROCEED_NOTE as M, recordLogOnlyValue as Ma, repairMalformedOutputsForReadOnly as Mi, UNSPECIFIED_SKIP_REASON as Mn, getBootstrapMarkerKey as Mo, UNREADABLE_ORPHANS_CONTAINER_ROW as Mr, StageLoadError as Ms, effectiveDeletionPolicy as Mt, INDEX_SETTLE_POLL_INTERVAL_MS as N, shareLogOnlyValues as Na, repairMalformedResourceEntriesForReadOnly as Ni, deleteIndeterminateGuards as Nn, isCrossRegionRedirect as No, UNREADABLE_RESOURCES_MAP_ROW as Nr, processStackMessages as Ns, isFinalSnapshotError as Nt, compensateRemovedDeletionProtection as O, literalSplitDelimitersOf as Oa, refuseMalformedResourcesForExport as Oi, CloudControlProvider as On, AssetModeResolver as Oo, passedParameterClassesOf as Or, PARTITION_TABLE as Os, PRE_DELETE_SNAPSHOT_TYPES as Ot, deleteTableWithIndexBusyRetry as P, createSecretMasker as Pa, repairMalformedResourcePropertiesForReadOnly as Pi, deleteSkipReason as Pn, parseBootstrapMarker as Po, deployRefusesOrphanRowsReason as Pr, defineOwnKey as Ps, refusesFinalSnapshot as Pt, reachableDivergentParameters as Q, STATE_SOURCED_CROSS_GENERATION_RULES as Qa, coerceWarmThroughput as Qi, assertSendableRoleArn as Qn, redactedDockerCause as Qo, malformedOutputsRefusalMessage as Qr, isWholeDynamicReferenceValue as Qt, hasCdkAutoDeleteTag as R, markSameGenerationBag as Ra, unreadableResourceEntries as Ri, disableInstanceApiTermination as Rn, buildDenyExternalAccessPolicy as Ro, hasReadableResources as Rr, ownValue as Rs, redactedDeleteAddressFields as Rt, isProtectionValueActive as S, liveMatchesUnresolvedTokenFrame as Sa, refuseMalformedResourceEntriesForOrphan as Si, CC_BROKEN_REASON as Sn, stringifyValue as So, cfnRefValueFromPhysicalId as Sr, MIGRATE_TMP_PREFIX as Ss, planRollback as St, DynamoDBGlobalTableProvider as T, carryLogOnlyValues as Ta, refuseMalformedResourcePropertiesForOrphan as Ti, wouldReturnToSdkProvider as Tn, createAssetRedirectResolver as To, parseWebACLArn as Tr, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Ts, getCurrentProducerRegions as Tt, createReadOnlyAttributeHealerFactory as U, dynamicReferenceTokens as Ua, NO_CC_HANDLERS_REASON as Ui, reEnableInstanceApiTermination as Un, describeDockerFailure as Uo, malformedExportSourceWarning as Ur, resolveAssemblyPath as Us, DeploymentEventsStore as Ut, markRefusedBeforeApplying as V, recoverMaskedOutput as Va, unwrittenCreateOnlyReplacement as Vi, observeThenDisableInstanceApiTermination as Vn, describeDockerCapturedOutput as Vo, malformedDriftResourcePropertiesWarning as Vr, displayAssemblyPath as Vs, updatePartialReason as Vt, bold as W, isUncertifiedBaselineMaskPosition as Wa, hasNoCloudControlHandlers as Wi, DiffCalculator as Wn, dockerSpawnEnvWithSensitive as Wo, malformedLocalOutputsWarning as Wr, clearBucketRegionCache as Ws, extractDeploymentEventError as Wt, computeParameterTaint as X, recordNoEchoAttributeValues as Xa, renderStatefulReason as Xi, applyRoleArnIfSet as Xn, partitionSensitiveEnv as Xo, malformedOrphansRefusalMessage as Xr, secretSafeKeyDisplay as Xt, yellow as Y, recordMaskOnlyValuesIn as Ya, isStatefulRecreateTargetSync as Yi, regionLessSecretName as Yn, isMalformedEnvKey as Yo, malformedOrphanRowsKeptWarning as Yr, secretBearingStateKeyWarning as Yt, namesAnyDeclaredParameter as Z, STATE_SOURCED_BASELINE_RULES as Za, WARM_THROUGHPUT_MEMBERS as Zi, assertFlagRoleArn as Zn, redactDockerArgvValues as Zo, malformedOrphansWarning as Zr, exportNameSecretExposure as Zt, makeCanonicalizePropertiesFn as _, canonicalLambdaFunctionName as _a, refuseMalformedResourceEntries as _i, refuseMalformedDesiredTags as _n, orphansAfterRollback as _o, carriesDynamicReference as _r, stateBucketExistenceConfirmed as _s, destroyStackRecordsView as _t, findNestedTemplateTreeDefect as a, configIntegerRefusal as aa, malformedStateRefusalMessage as ai, DEFAULT_RESOURCE_WARN_AFTER_MS as an, S3StateBackend as ao, envCredentialsAreAssumedRole as ar, getDockerImageBySourceHash as as, dropSettledNestedJournals as at, recordedProtectionNote as b, DagBuilder as ba, refuseMalformedResourceEntriesForImport as bi, definedAttributes as bn, AssetPublisher as bo, keepsSecretReferenceToken as br, CFN_TEMPLATE_BODY_LIMIT as bs, recordAfterRollbackUpdate as bt, renderNestedTemplateTreeDefect as c, replayWarn as ca, refuseMalformedNestedChildOutputs as ci, earliestDefined as cn, acceptedCreateOnlyDropsOf as co, s3BucketDomainName as cr, getDefaultStateBucketName as cs, recordDisplacedSkips as ct, conditionInputsFrom as d, requireConfigString as da, refuseMalformedOrphans as di, withCreateTokenLedger as dn, hasReadableExportSet as do, s3BucketWebsiteUrl as dr, resolveAutoAssetStorage as ds, withNestedRevertRun as dt, toCfnInteger as ea, malformedRenderedContainersWarning as ei, collectDeclaredOutputNames as en, TEMPLATE_SOURCED_RULES as eo, isIamRoleArn as er, runDockerStreaming as es, makeSiblingClaimReader as et, parentSuppliedValues as f, prefetchCreateOnlyPropertyPaths as fa, refuseMalformedOrphansForDestroy as fi, acquireIdempotencyToken as fn, hasReasonlessBaselineRefusal as fo, coerceParameterTypedValue as fr, resolveCaptureObservedState as fs, getCurrentNestedStackContext as ft, mergeNoChangeOutputs as g, markAuxiliaryFailure as ga, refuseMalformedResourceAttributesForOrphan as gi, readTagList as gn, isReadableBag as go, isImpossibleEmptyStoredAttribute as gr, resolveUseCdkBootstrapAssets as gs, awaitInFlightSibling as gt, keptWholeReasonText as h, withRetry as ha, refuseMalformedOutputsForDestroy as hi, planTagDiff as hn, importableOutputs as ho, getAccountInfo as hr, resolveStateBucketWithDefaultAndSource as hs, replayRollback as ht, childTemplateLoader as i, configBooleanRefusal as ia, malformedScrubResourceEntriesRefusalMessage as ii, DEFAULT_RESOURCE_TIMEOUT_MS as in, isLockInfoExpired as io, callerEnvCredentials as ir, AssetManifestLoader as is, displacedPhysicalIdShown as it, resolveDynamoDbDeleteBudgetMs as j, recordLogOnlyParameterValue as ja, repairMalformedOrphansForReadOnly as ji, unchangedBehindSecretReference as jn, ensureAssetStorage as jo, STATE_RESOURCES_MALFORMED as jr, AssemblyReader as js, createPreDeleteFinalSnapshot as jt, deleteBudgetKey as k, logOnlyValueCount as ka, refuseMalformedState as ki, slowCcOperationTimeoutMs as kn, BOOTSTRAP_MARKER_PREFIX as ko, JSON_LISTING_HOLE_VALUE as kr, canonicalizeRegion as ks, buildFinalSnapshotIdentifier as kt, templateIdentity as l, requireConfigArray as la, refuseMalformedOrphanRecords as li, ledgerForStack as ln, describeRegionValueKind as lo, s3BucketDualStackDomainName as lr, getLegacyStateBucketName as ls, revertNestedChildFromJournal as lt, isSecretBearingReferenceString as m, describeTypeWithThrottleRetry as ma, refuseMalformedOutputs as mi, DBPROXY_TAG_OPTIONS as mn, importableOutputKeys as mo, parameterTypeMayLoseSecretIdentity as mr, resolveStateBucketWithDefault as ms, replayFailedOperations as mt, IMPLICIT_DELETE_DEPENDENCIES as n, coerceCfnBoolean as na, malformedResourcePropertiesWarning as ni, isExportAliasCollision as nn, isSingleDynamicReferenceToken as no, AWS_CREDENTIAL_ENV_KEYS as nr, escapeRegExp$2 as ns, NESTED_PENDING_PARENT_REASON as nt, isAbsoluteAssetPath as o, configStringRefusal as oa, previewableOrphanRecords as oi, maskingRetryLogger as on, rebuildClientForBucketRegion as oo, isSettledInstanceState as or, Synthesizer as os, getNestedRevertRun as ot, readRecordedConditionVerdicts as p, templateResourceTypes as pa, refuseMalformedOrphansForOrphan as pi, DBPROXY_TAGS_WHAT as pn, hasUnverifiableParameterRefusal as po, isUnboundTemplateParameter as pr, resolveSkipPrefix as ps, withNestedStackContext as pt, green as q, carriesSecretMask as qa, MULTI_REGION_RECREATE_BLOCKED_TYPES as qi, classifyReplaySecretRegion as qn, getDockerCmd as qo, malformedOrphanRecordsRefusalMessage as qr, exportAliasCollisionScrubWarning as qt, computeImplicitDeleteEdges as r, coerceCfnInteger as ra, malformedResourcesWarning as ri, bindingSkippedOutputs as rn, LockManager as ro, applyCallerIdentityCredentials as rr, stripControlChars as rs, displacedOpClause as rt, listNestedTemplateRows as s, readConfigString as sa, refuseDivergentRecordRegionForDestroy as si, RollbackInlinePolicyWriters as sn, splitImportedOps as so, s3BucketArn as sr, synthesisStatusMessage as ss, nestedChildStackName as st, DeployEngine as t, toFiniteNumber as ta, malformedResourceEntriesWarning as ti, collectPublishedOutputNames as tn, WHOLE_DYNAMIC_REFERENCE_PATTERN as to, sendableAssumeRoleCommand as tr, warnFinchArgvExposure as ts, planOrphanAdoption as tt, conditionFingerprint as u, requireConfigObject as ua, refuseMalformedOrphanRecordsForDestroy as ui, reserveStackCreateToken as un, exportNamesCarriedFrom as uo, s3BucketRegionalDomainName as ur, resolveApp as us, revertedNestedRowIds as ut, withResourceDeadline as v, lambdaFunctionNameForMask as va, refuseMalformedResourceEntriesForDeploy as vi, tagMapAsList as vn, orphansCarriedFrom as vo, carriesFetchableDynamicReference as vr, warnDeprecatedNoPrefixCliFlag as vs, getStackRecords as vt, readProtection as w, recordNestedStackParameterExpressions as wa, refuseMalformedResourcePropertiesForExport as wi, ccBrokenReason as wn, buildAssetRedirectMap as wo, refStateLookupFromResource as wr, uploadCfnTemplate as ws, findNestedStackTypeChanges as wt, PROTECTION_PROPERTY_BY_TYPE as x, TemplateParser as xa, refuseMalformedResourceEntriesForImportSave as xi, stringifyIfAssigned as xn, isSensitiveAttributeName as xo, AWS_NO_VALUE as xr, CFN_TEMPLATE_URL_LIMIT as xs, planFailedOps as xt, recordedProtectionEvidence as y, sameLambdaFunctionAddress as ya, refuseMalformedResourceEntriesForDestroy as yi, tagPlanWarning as yn, shouldRetainResource as yo, isNamelessDynamicReferenceError as yr, ssmResolvedValueType as ys, withStackRecords as yt, isTruthyCfnBoolean as z, redactSecretsForState as za, findActionableSilentDrops as zi, ec2InstanceProtectionSite as zn, buildDockerImage as zo, isReadableOrphanRecord as zr, absoluteAssemblyPathEscape as zs, redactedDeleteAddressSkip as zt };
36539
+ //# sourceMappingURL=deploy-engine-C35Ctso3.js.map