@go-to-k/cdkd 0.294.9 → 0.294.11

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.
Files changed (24) hide show
  1. package/dist/{asg-provider-3uLGAhIx.js → asg-provider-CbHiTBaE.js} +2 -2
  2. package/dist/{asg-provider-3uLGAhIx.js.map → asg-provider-CbHiTBaE.js.map} +1 -1
  3. package/dist/cli.js +2 -2
  4. package/dist/{deploy-engine-BTOCDCWf.js → deploy-engine-CMRU0DTu.js} +1877 -270
  5. package/dist/deploy-engine-CMRU0DTu.js.map +1 -0
  6. package/dist/{iam-role-provider-CBT2LPe1.js → iam-role-provider-DOKKlLrC.js} +2 -2
  7. package/dist/{iam-role-provider-CBT2LPe1.js.map → iam-role-provider-DOKKlLrC.js.map} +1 -1
  8. package/dist/index.d.ts +43 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +2 -2
  11. package/dist/{neptune-provider-BQ-CGoYJ.js → neptune-provider-CS-r4Ufj.js} +2 -2
  12. package/dist/{neptune-provider-BQ-CGoYJ.js.map → neptune-provider-CS-r4Ufj.js.map} +1 -1
  13. package/dist/{program-DMJnrQOG.js → program-dQFaGjL1.js} +234 -190
  14. package/dist/program-dQFaGjL1.js.map +1 -0
  15. package/dist/{provider-classes-DCbt28RB.js → provider-classes-5NUmLSTV.js} +182 -60
  16. package/dist/provider-classes-5NUmLSTV.js.map +1 -0
  17. package/dist/{rds-provider-J6zl27x3.js → rds-provider-l9F4Y8YY.js} +2 -2
  18. package/dist/{rds-provider-J6zl27x3.js.map → rds-provider-l9F4Y8YY.js.map} +1 -1
  19. package/dist/{version-QrNvZCe0.js → version-DIQcU8CA.js} +2 -2
  20. package/dist/{version-QrNvZCe0.js.map → version-DIQcU8CA.js.map} +1 -1
  21. package/package.json +1 -1
  22. package/dist/deploy-engine-BTOCDCWf.js.map +0 -1
  23. package/dist/program-DMJnrQOG.js.map +0 -1
  24. package/dist/provider-classes-DCbt28RB.js.map +0 -1
@@ -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-QrNvZCe0.js";
5
+ import { t as getCdkdVersion } from "./version-DIQcU8CA.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,6 +15736,927 @@ 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
+
15749
+ //#endregion
15750
+ //#region src/deployment/masked-property-fingerprints.ts
15751
+ const FINGERPRINT_LAYOUT$1 = 1;
15752
+ const INPUT_FINGERPRINT_LAYOUT = 2;
15753
+ function canonicalJson$2(value) {
15754
+ if (value === void 0) return "null";
15755
+ if (Array.isArray(value)) return `[${value.map(canonicalJson$2).join(",")}]`;
15756
+ if (value !== null && typeof value === "object") {
15757
+ const record = value;
15758
+ return `{${Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson$2(record[key])}`).join(",")}}`;
15759
+ }
15760
+ return JSON.stringify(value) ?? "null";
15761
+ }
15762
+ const REFUSED_FINGERPRINT = "refused:secret-in-template";
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
+ }
15778
+ function templateCarriesNeedle(templateValue, secrets) {
15779
+ const text = canonicalJson$2(templateValue);
15780
+ for (const needle of printingCorpusOf(secrets).keys()) {
15781
+ if (needle.length < 4) continue;
15782
+ if (text.includes(needle) || text.includes(JSON.stringify(needle).slice(1, -1))) return true;
15783
+ }
15784
+ return false;
15785
+ }
15786
+ function maskedPropertyFingerprint(templateValue) {
15787
+ const digest = createHash("sha256").update(canonicalJson$2({
15788
+ layout: FINGERPRINT_LAYOUT$1,
15789
+ value: templateValue
15790
+ })).digest("hex");
15791
+ return `${FINGERPRINT_PREFIX}${digest}`;
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
+ }
16512
+ function maskedPropertyFingerprintsFor(recordedProperties, templateProps) {
16513
+ const entries = [];
16514
+ for (const key of Object.keys(recordedProperties)) {
16515
+ if (!Object.hasOwn(templateProps, key)) continue;
16516
+ if (!carriesSecretMask(recordedProperties[key])) continue;
16517
+ entries.push([key, maskedPropertyFingerprint(templateProps[key])]);
16518
+ }
16519
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
16520
+ }
16521
+ function maskedPropertyFingerprintsOf(record) {
16522
+ const read = /* @__PURE__ */ new Map();
16523
+ if (record === null || typeof record !== "object") return read;
16524
+ const field = record.maskedPropertyFingerprints;
16525
+ if (!isPlainObject$2(field)) return read;
16526
+ for (const [key, value] of Object.entries(field)) if (typeof value === "string" && value.startsWith(FINGERPRINT_PREFIX)) read.set(key, value);
16527
+ return read;
16528
+ }
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) {
16553
+ const recorded = maskedPropertyFingerprintsOf(record);
16554
+ if (recorded.size === 0) return [];
16555
+ const properties = record.properties;
16556
+ if (properties === null || typeof properties !== "object") return [];
16557
+ const inputs = maskedPropertyInputFingerprintsOf(record);
16558
+ const moved = [];
16559
+ for (const [key, fingerprint] of recorded) {
16560
+ if (!Object.hasOwn(templateProps, key) || !Object.hasOwn(properties, key)) continue;
16561
+ if (!carriesSecretMask(properties[key])) continue;
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);
16574
+ }
16575
+ return moved;
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
+ }
16594
+ const writtenFromDeployedTemplate = /* @__PURE__ */ new WeakSet();
16595
+ function markWrittenFromDeployedTemplate(bag) {
16596
+ writtenFromDeployedTemplate.add(bag);
16597
+ return bag;
16598
+ }
16599
+ function withMaskedPropertyFingerprints(scrubbed, writtenBag, templateProps, secrets, noEchoParameterValues, inputFingerprints) {
16600
+ if (templateProps === void 0) return scrubbed;
16601
+ const corpora = [secrets, noEchoParameterValues].filter((corpus) => corpus !== void 0);
16602
+ const written = writtenBag !== null && typeof writtenBag === "object" && writtenFromDeployedTemplate.has(writtenBag);
16603
+ const { maskedPropertyFingerprints: previous, maskedPropertyInputFingerprints: previousInputs, ...rest } = scrubbed;
16604
+ let fingerprints;
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;
16611
+ if (corpora.length === 0) return scrubbed;
16612
+ fingerprints = { ...previous };
16613
+ inputs = isPlainObject$2(previousInputs) ? { ...previousInputs } : void 0;
16614
+ }
16615
+ if (fingerprints !== void 0 && corpora.length > 0) {
16616
+ const refused = Object.keys(fingerprints).filter((key) => Object.hasOwn(templateProps, key) && corpora.some((corpus) => templateCarriesNeedle(templateProps[key], corpus)));
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
+ }
16624
+ }
16625
+ if (!written && JSON.stringify(fingerprints) === JSON.stringify(previous) && JSON.stringify(inputs) === JSON.stringify(previousInputs)) return scrubbed;
16626
+ return {
16627
+ ...rest,
16628
+ ...fingerprints !== void 0 && { maskedPropertyFingerprints: fingerprints },
16629
+ ...inputs !== void 0 && { maskedPropertyInputFingerprints: inputs }
16630
+ };
16631
+ }
16632
+ function backfillMaskedPropertyFingerprints(resources, template, noEchoParameterValues) {
16633
+ const declared = template?.Resources;
16634
+ if (declared === void 0 || declared === null) return 0;
16635
+ let stamped = 0;
16636
+ for (const [logicalId, record] of Object.entries(resources)) {
16637
+ if (record === null || typeof record !== "object") continue;
16638
+ const field = record.maskedPropertyFingerprints;
16639
+ if (field !== void 0 && (field === null || typeof field !== "object" || Array.isArray(field))) continue;
16640
+ const existing = field ?? {};
16641
+ if (!Object.hasOwn(declared, logicalId)) continue;
16642
+ const definition = declared[logicalId];
16643
+ if (definition === void 0 || definition.Type !== record.resourceType) continue;
16644
+ const properties = record.properties;
16645
+ if (properties === null || typeof properties !== "object" || Array.isArray(properties)) continue;
16646
+ const fingerprints = maskedPropertyFingerprintsFor(properties, definition.Properties ?? {});
16647
+ if (fingerprints === void 0) continue;
16648
+ const templateProps = definition.Properties ?? {};
16649
+ const added = Object.entries(fingerprints).filter(([key]) => !Object.hasOwn(existing, key)).map(([key, value]) => noEchoParameterValues !== void 0 && templateCarriesNeedle(templateProps[key], noEchoParameterValues) ? [key, REFUSED_FINGERPRINT] : [key, value]);
16650
+ if (added.length === 0) continue;
16651
+ resources[logicalId] = {
16652
+ ...record,
16653
+ maskedPropertyFingerprints: Object.fromEntries([...Object.entries(existing), ...added])
16654
+ };
16655
+ stamped++;
16656
+ }
16657
+ return stamped;
16658
+ }
16659
+
15686
16660
  //#endregion
15687
16661
  //#region src/deployment/drain-budget.ts
15688
16662
  const drainDeadlines = new AsyncLocalStorage();
@@ -15980,6 +16954,49 @@ const DEPLOY_RESOLVED_REFERENCE_SERVICES = /* @__PURE__ */ new Set([
15980
16954
  "ssm",
15981
16955
  "ssm-secure"
15982
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
+ }
15983
17000
  function keepsSecretReferenceToken(resolvedName) {
15984
17001
  return dynamicReferenceTokens(resolvedName).some((token) => DEPLOY_RESOLVED_REFERENCE_SERVICES.has(token.slice(10, -2).split(":")[0] ?? ""));
15985
17002
  }
@@ -17766,6 +18783,13 @@ async function resolveTemplateLeafReferences(value, context) {
17766
18783
  return (await this.resolveDynamicReferencesWithLogTwin(value, value, context)).result;
17767
18784
  }
17768
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
+ }
17769
18793
  const pattern = /\{\{resolve:([^}]+)\}\}/g;
17770
18794
  let result = value;
17771
18795
  let twin = logTwin;
@@ -18228,6 +19252,15 @@ function rethrowStructuralSubFailure(varName, error, context) {
18228
19252
  if (!this.subPlaceholderNamesADeclaredTemplateEntity(varName, context)) return;
18229
19253
  throw error;
18230
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
+ }
18231
19264
  function subListRefusal(subject, value, context) {
18232
19265
  if (!Array.isArray(value)) return void 0;
18233
19266
  const count = `${value.length} item${value.length === 1 ? "" : "s"}`;
@@ -18337,11 +19370,13 @@ async function resolveSub(subArgs, context, source) {
18337
19370
  this.rethrowStructuralSubFailure(varNameStr, getAttError, context);
18338
19371
  this.logger.warn(this.displayMasked(this.subPlaceholderWarning(varNameStr, getAttError), context));
18339
19372
  replacement = match[0];
19373
+ noteKeptSubPlaceholder(varNameStr, match[0], getAttError, context);
18340
19374
  }
18341
19375
  else {
18342
19376
  this.rethrowStructuralSubFailure(varNameStr, refError, context);
18343
19377
  this.logger.warn(this.displayMasked(this.subPlaceholderWarning(varNameStr, refError), context));
18344
19378
  replacement = match[0];
19379
+ noteKeptSubPlaceholder(varNameStr, match[0], refError, context);
18345
19380
  }
18346
19381
  }
18347
19382
  }
@@ -18858,16 +19893,6 @@ function displayLeaf(value, context) {
18858
19893
  return this.displayMasked(this.logTextOfLeaf(value, context), context);
18859
19894
  }
18860
19895
 
18861
- //#endregion
18862
- //#region src/deployment/assumed-conditions.ts
18863
- const assumedConditionNames = /* @__PURE__ */ new WeakMap();
18864
- function recordAssumedConditions(conditions, assumed) {
18865
- assumedConditionNames.set(conditions, assumed);
18866
- }
18867
- function conditionsAssumedFalse(conditions) {
18868
- return assumedConditionNames.get(conditions) ?? /* @__PURE__ */ new Set();
18869
- }
18870
-
18871
19896
  //#endregion
18872
19897
  //#region src/deployment/intrinsic-resolver/params-conditions.ts
18873
19898
  async function resolveParameters(template, userParameters, options) {
@@ -19409,7 +20434,7 @@ var DiffCalculator = class DiffCalculator {
19409
20434
  conditionalReplacementVerdict(resourceType, propertyPath, oldValue, newValue) {
19410
20435
  return this.replacementRules.conditionalReplacementVerdict(resourceType, propertyPath, oldValue, newValue);
19411
20436
  }
19412
- async calculateDiff(currentState, desiredTemplate, resolveFn, canonicalizeProperties, allowedUnsupportedProperties, freshParameters, maskForLog, recreateTargets) {
20437
+ async calculateDiff(currentState, desiredTemplate, resolveFn, canonicalizeProperties, allowedUnsupportedProperties, freshParameters, maskForLog, recreateTargets, maskedInputs) {
19413
20438
  const changes = /* @__PURE__ */ new Map();
19414
20439
  refuseMalformedResourceEntriesForDeploy(currentState, void 0, void 0);
19415
20440
  refuseMalformedResourceProperties(currentState, void 0, void 0);
@@ -19473,6 +20498,25 @@ var DiffCalculator = class DiffCalculator {
19473
20498
  if (droppedKeys.length > 0) this.logger.warn(`${logicalId} (${desiredResource.Type}): part of the declared properties cannot be sent as declared and is ignored when comparing against deployed state — the provider narrows them (${droppedKeys.join(", ")}). Fix the template to declare only what the resource supports; until then changes to the ignored keys have no effect.`);
19474
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.`);
19475
20500
  const propertyChanges = await this.compareProperties(desiredResource.Type, currentPropsForCompare, desiredPropsForCompare, maskForLog);
20501
+ const reported = new Set(propertyChanges.map((pc) => pc.path));
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) {
20506
+ if (reported.has(key)) continue;
20507
+ if (!Object.hasOwn(currentPropsForCompare, key)) continue;
20508
+ if (!Object.hasOwn(desiredPropsForCompare, key)) continue;
20509
+ const oldValue = currentPropsForCompare[key];
20510
+ const newValue = desiredPropsForCompare[key];
20511
+ propertyChanges.push({
20512
+ path: key,
20513
+ oldValue,
20514
+ newValue,
20515
+ requiresReplacement: await this.maskedEditRequiresReplacement(desiredResource.Type, key, oldValue, newValue),
20516
+ maskedExpressionChanged: true
20517
+ });
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)`);
20519
+ }
19476
20520
  const attributeChanges = this.compareAttributes(currentResource, desiredResource);
19477
20521
  if (propertyChanges.length > 0 || attributeChanges.length > 0) {
19478
20522
  changes.set(logicalId, {
@@ -19839,6 +20883,11 @@ var DiffCalculator = class DiffCalculator {
19839
20883
  }
19840
20884
  return changes;
19841
20885
  }
20886
+ async maskedEditRequiresReplacement(resourceType, key, oldValue, newValue) {
20887
+ if (this.replacementRules.requiresReplacement(resourceType, key, oldValue, newValue)) return true;
20888
+ if (this.replacementRules.isClassified(resourceType, key)) return false;
20889
+ return (await getCreateOnlyPropertyPaths(resourceType)).some((path) => path.length === 1 && path[0] === key);
20890
+ }
19842
20891
  static INTRINSIC_KEYS = INTRINSIC_KEYS;
19843
20892
  static isIntrinsic(value) {
19844
20893
  if (value === null || value === void 0 || typeof value !== "object" || Array.isArray(value)) return false;
@@ -20779,7 +21828,7 @@ var CloudControlProvider = class {
20779
21828
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
20780
21829
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
20781
21830
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
20782
- const { ASGProvider } = await import("./asg-provider-3uLGAhIx.js");
21831
+ const { ASGProvider } = await import("./asg-provider-CbHiTBaE.js");
20783
21832
  const delegateRegion = ambientRegion();
20784
21833
  let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
20785
21834
  if (asgProvider === void 0) {
@@ -20885,7 +21934,7 @@ var CloudControlProvider = class {
20885
21934
  const family = SDK_DELETE_FAMILIES.get(resourceType);
20886
21935
  const cached = this.sdkDeleteDelegates.get(family);
20887
21936
  if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
20888
- const provider = family === "rds" ? new (await (import("./rds-provider-J6zl27x3.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-BQ-CGoYJ.js"))).NeptuneProvider({ region: ccRegion });
21937
+ const provider = family === "rds" ? new (await (import("./rds-provider-l9F4Y8YY.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-CS-r4Ufj.js"))).NeptuneProvider({ region: ccRegion });
20889
21938
  this.sdkDeleteDelegates.set(family, {
20890
21939
  region: ccRegion,
20891
21940
  provider
@@ -24938,30 +25987,47 @@ async function reserveStackCreateToken(options) {
24938
25987
  //#region src/deployment/inline-policy-claims.ts
24939
25988
  function isInlinePolicyClaimedByCompletedWriter(args, kind, principal, policyName) {
24940
25989
  const { selfLogicalId, writers, changes, stateResources } = args;
24941
- const same = (a, b) => typeof a === "string" && IAM_NAME.test(a) && a.toLowerCase() === b.toLowerCase();
24942
25990
  for (const [lid, write] of writers) {
24943
25991
  if (lid === selfLogicalId || !Object.hasOwn(stateResources, lid)) continue;
24944
25992
  const record = stateResources[lid];
24945
25993
  if (record.provisionedBy === "cc-api") continue;
24946
25994
  const props = record.properties ?? {};
24947
25995
  if (record.resourceType === "AWS::IAM::Policy") {
24948
- if (!same(record.physicalId, policyName)) continue;
25996
+ if (!sameIamName(record.physicalId, policyName)) continue;
24949
25997
  const listed = props[POLICY_LIST_FIELDS[kind]];
24950
- if (Array.isArray(listed) && listed.some((p) => same(p, principal))) return true;
25998
+ if (Array.isArray(listed) && listed.some((p) => sameIamName(p, principal))) return true;
24951
25999
  continue;
24952
26000
  }
24953
26001
  if (!Object.hasOwn(PRINCIPAL_KINDS, record.resourceType)) continue;
24954
26002
  if (PRINCIPAL_KINDS[record.resourceType] !== kind) continue;
24955
- if (!same(record.physicalId, principal)) continue;
26003
+ if (!sameIamName(record.physicalId, principal)) continue;
24956
26004
  if (write !== "create" && !ownPoliciesChange(changes.get(lid))) continue;
24957
26005
  const policies = props["Policies"];
24958
26006
  if (!Array.isArray(policies)) continue;
24959
- if (policies.some((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && same(entry["PolicyName"], policyName))) return true;
26007
+ if (policies.some((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && sameIamName(entry["PolicyName"], policyName))) return true;
24960
26008
  }
24961
26009
  return false;
24962
26010
  }
24963
26011
  var RollbackInlinePolicyWriters = class {
24964
26012
  entries = /* @__PURE__ */ new Map();
26013
+ removals = /* @__PURE__ */ new Map();
26014
+ unsettled = /* @__PURE__ */ new Map();
26015
+ notePending(ops) {
26016
+ for (const op of ops) if (!this.unsettled.has(op)) this.unsettled.set(op, {
26017
+ logicalId: op.logicalId,
26018
+ state: "pending"
26019
+ });
26020
+ }
26021
+ noteOutcome(op, completed) {
26022
+ if (!completed) {
26023
+ this.unsettled.set(op, {
26024
+ logicalId: op.logicalId,
26025
+ state: "failed"
26026
+ });
26027
+ return;
26028
+ }
26029
+ for (const [key, entry] of this.unsettled) if (key === op || entry.logicalId === op.logicalId) this.unsettled.delete(key);
26030
+ }
24965
26031
  record(logicalId, write, record, policiesChanged, via) {
24966
26032
  if (via === "cc-api") {
24967
26033
  this.entries.delete(logicalId);
@@ -24993,15 +26059,100 @@ var RollbackInlinePolicyWriters = class {
24993
26059
  }]
24994
26060
  });
24995
26061
  }
24996
- return isInlinePolicyClaimedByCompletedWriter({
26062
+ const claimed = isInlinePolicyClaimedByCompletedWriter({
24997
26063
  selfLogicalId: logicalId,
24998
26064
  writers,
24999
26065
  changes,
25000
26066
  stateResources
25001
26067
  }, kind, principal, policyName);
26068
+ if (!claimed) {
26069
+ const key = removalKey(kind, principal, policyName);
26070
+ const noted = this.removals.get(key) ?? {
26071
+ kind,
26072
+ principal,
26073
+ policyName,
26074
+ removers: /* @__PURE__ */ new Map()
26075
+ };
26076
+ noted.removers.set(logicalId, stateResources[logicalId]);
26077
+ this.removals.set(key, noted);
26078
+ }
26079
+ return claimed;
25002
26080
  };
25003
26081
  }
26082
+ takeHeldRemovals(stateResources) {
26083
+ const held = [];
26084
+ for (const [key, { kind, principal, policyName, removers }] of this.removals) {
26085
+ const { holders, unreadable } = inlinePolicyHolders(stateResources, kind, principal, policyName);
26086
+ const others = holders.filter((h) => !removers.has(h.logicalId) || stateResources[h.logicalId] !== removers.get(h.logicalId));
26087
+ if (others.length === 0) continue;
26088
+ this.removals.delete(key);
26089
+ const open = new Set([...this.unsettled.values()].map((u) => u.logicalId));
26090
+ const unsettled = [...new Set(others.map((h) => h.logicalId))].filter((id) => open.has(id));
26091
+ held.push({
26092
+ kind,
26093
+ holders: others,
26094
+ unreadable,
26095
+ unsettled
26096
+ });
26097
+ }
26098
+ return held;
26099
+ }
25004
26100
  };
26101
+ function inlinePolicyHolders(stateResources, kind, principal, policyName) {
26102
+ const holders = [];
26103
+ const unreadable = [];
26104
+ const unnamed = (v) => typeof v !== "string" || !IAM_NAME.test(v);
26105
+ for (const [logicalId, record] of Object.entries(stateResources)) {
26106
+ if (record === null || typeof record !== "object") continue;
26107
+ const props = record.properties ?? {};
26108
+ if (record.resourceType === "AWS::IAM::Policy") {
26109
+ const nameMatches = sameIamName(record.physicalId, policyName);
26110
+ if (!nameMatches && !unnamed(record.physicalId)) continue;
26111
+ const listed = props[POLICY_LIST_FIELDS[kind]];
26112
+ const entries = Array.isArray(listed) ? listed : [];
26113
+ const named = entries.find((p) => sameIamName(p, principal));
26114
+ if (nameMatches && typeof named === "string") holders.push({
26115
+ logicalId,
26116
+ principal: named,
26117
+ policyName: record.physicalId,
26118
+ document: props["PolicyDocument"]
26119
+ });
26120
+ else if (named !== void 0 || entries.some(unnamed)) unreadable.push(logicalId);
26121
+ continue;
26122
+ }
26123
+ if (!Object.hasOwn(PRINCIPAL_KINDS, record.resourceType)) continue;
26124
+ if (PRINCIPAL_KINDS[record.resourceType] !== kind) continue;
26125
+ const principalMatches = sameIamName(record.physicalId, principal);
26126
+ if (!principalMatches && !unnamed(record.physicalId)) continue;
26127
+ const policies = props["Policies"];
26128
+ if (!Array.isArray(policies)) continue;
26129
+ for (const entry of policies) {
26130
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue;
26131
+ const name = entry["PolicyName"];
26132
+ if (principalMatches && sameIamName(name, policyName)) holders.push({
26133
+ logicalId,
26134
+ principal: record.physicalId,
26135
+ policyName: name,
26136
+ document: entry["PolicyDocument"]
26137
+ });
26138
+ else if (unnamed(name) || sameIamName(name, policyName)) unreadable.push(logicalId);
26139
+ }
26140
+ }
26141
+ return {
26142
+ holders,
26143
+ unreadable: [...new Set(unreadable)]
26144
+ };
26145
+ }
26146
+ function sameIamName(a, b) {
26147
+ return typeof a === "string" && IAM_NAME.test(a) && a.toLowerCase() === b.toLowerCase();
26148
+ }
26149
+ function removalKey(kind, principal, policyName) {
26150
+ return JSON.stringify([
26151
+ kind,
26152
+ principal.toLowerCase(),
26153
+ policyName.toLowerCase()
26154
+ ]);
26155
+ }
25005
26156
  const IAM_NAME = /^[\w+=,.@-]+$/;
25006
26157
  const POLICY_LIST_FIELDS = {
25007
26158
  role: "Roles",
@@ -25561,6 +26712,18 @@ function deploymentEventsIndexKey(prefix, stackName, region) {
25561
26712
  function deploymentsDirPrefix(prefix, stackName, region) {
25562
26713
  return `${prefix}/${stackName}/${region}/deployments/`;
25563
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
+ }
25564
26727
  function runIdTimestampMs(runId) {
25565
26728
  const m = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})Z/.exec(runId);
25566
26729
  if (!m) return null;
@@ -25705,7 +26868,7 @@ var DeploymentEventsStore = class {
25705
26868
  return runId !== null && runId < cutoff;
25706
26869
  });
25707
26870
  if (stale.length === 0) return;
25708
- await this.backend.deleteRawObjects(stale);
26871
+ await deleteAndPurgeEventObjects(this.backend, stale, dirPrefix);
25709
26872
  this.logger.debug(`Pruned ${stale.length} superseded deployment-event stream(s) for ${this.stackName} (${this.region})`);
25710
26873
  }
25711
26874
  warnOnce(message) {
@@ -25797,7 +26960,7 @@ var DeploymentEventsReader = class {
25797
26960
  const indexExisted = keys.includes(indexKey);
25798
26961
  if (opts.all === true) {
25799
26962
  const toDelete = runIdsDesc.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
25800
- await this.backend.deleteRawObjects([...toDelete, indexKey]);
26963
+ await deleteAndPurgeEventObjects(this.backend, [...toDelete, indexKey], dirPrefix);
25801
26964
  return {
25802
26965
  deletedRunIds: runIdsDesc,
25803
26966
  remainingRunIds: [],
@@ -25823,35 +26986,39 @@ var DeploymentEventsReader = class {
25823
26986
  const deletedSet = new Set(candidates);
25824
26987
  const deleteKeys = candidates.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
25825
26988
  const remainingRunIds = runIdsDesc.filter((id) => !deletedSet.has(id));
25826
- const indexDeleted = await this.rewriteIndexAfterPrune(indexKey, stackName, region, deletedSet, remainingRunIds.length === 0, indexExisted);
25827
- 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);
25828
26999
  return {
25829
27000
  deletedRunIds: candidates,
25830
27001
  remainingRunIds,
25831
- indexDeleted
27002
+ indexDeleted: false
25832
27003
  };
25833
27004
  }
25834
- async rewriteIndexAfterPrune(indexKey, stackName, region, deletedRunIds, noRunsRemain, indexExisted) {
25835
- if (noRunsRemain) {
25836
- await this.backend.deleteRawObjects([indexKey]);
25837
- return indexExisted;
25838
- }
27005
+ async rewriteIndexAfterPrune(indexKey, stackName, region, deletedRunIds) {
25839
27006
  let raw;
25840
27007
  try {
25841
27008
  raw = await this.backend.getRawObject(indexKey);
25842
27009
  } catch {
25843
- return false;
27010
+ return;
25844
27011
  }
25845
- if (raw === null) return false;
27012
+ if (raw === null) return;
25846
27013
  let parsed;
25847
27014
  try {
25848
27015
  parsed = JSON.parse(raw);
25849
27016
  } catch {
25850
- return false;
27017
+ return;
25851
27018
  }
25852
- if (!Array.isArray(parsed.runs)) return false;
27019
+ if (!Array.isArray(parsed.runs)) return;
25853
27020
  const remaining = parsed.runs.filter((r) => !deletedRunIds.has(r.runId));
25854
- if (remaining.length === parsed.runs.length) return false;
27021
+ if (remaining.length === parsed.runs.length) return;
25855
27022
  const file = {
25856
27023
  indexVersion: 1,
25857
27024
  stackName,
@@ -25860,7 +27027,6 @@ var DeploymentEventsReader = class {
25860
27027
  lastModified: Date.now()
25861
27028
  };
25862
27029
  await this.backend.putRawObject(indexKey, JSON.stringify(file, null, 2));
25863
- return false;
25864
27030
  }
25865
27031
  };
25866
27032
 
@@ -25877,6 +27043,31 @@ function updatePartialMessage(reason) {
25877
27043
  return `partial (${reason})`;
25878
27044
  }
25879
27045
 
27046
+ //#endregion
27047
+ //#region src/provisioning/redacted-delete-address.ts
27048
+ function isRedactedRecordedValue(value) {
27049
+ if (carriesSecretMask(value)) return true;
27050
+ let text;
27051
+ try {
27052
+ text = typeof value === "string" ? value : JSON.stringify(value);
27053
+ } catch {
27054
+ return false;
27055
+ }
27056
+ return text !== void 0 && dynamicReferenceTokens(text).length > 0;
27057
+ }
27058
+ const REDACTED_DELETE_ADDRESS_SKIP_REASON = "redacted address property in state — no delete issued";
27059
+ function redactedDeleteAddressFields(fields) {
27060
+ return Object.keys(fields).filter((key) => isRedactedRecordedValue(fields[key]));
27061
+ }
27062
+ function redactedDeleteAddressSkip(logger, logicalId, what, redactedFields) {
27063
+ if (redactedFields.length === 0) return void 0;
27064
+ logger.warn(safeMsg`${what} ${logicalId} is recorded in state with ${redactedFields.join(", ")} ` + "redacted (the '***' mask of a NoEcho value it read, or a secret '{{resolve:...}}' reference), which names nothing in AWS; skipping deletion — no AWS call is issued, so the resource is LEFT IN PLACE unless a parent resource this run also deletes removes it (then only the record is stale). Re-deploying records the same redaction again. The state record is KEPT and the run reports the skip: on 'cdkd destroy' / 'cdkd state destroy' (which exits non-zero) and, since issue 1762, on the plain DELETE of a resource removed from the template during cdkd deploy. Remove the resource by hand, then clear the stack's records with 'cdkd state orphan <stack>' — that command drops EVERY record for the stack, not just this one. NOTE a deploy-side REPLACEMENT or rollback delete instead FAILS the resource (https://github.com/go-to-k/cdkd/issues/1762) — the old resource is left untracked there, so remove it by hand.");
27065
+ return {
27066
+ outcome: "skipped",
27067
+ reason: REDACTED_DELETE_ADDRESS_SKIP_REASON
27068
+ };
27069
+ }
27070
+
25880
27071
  //#endregion
25881
27072
  //#region src/provisioning/final-snapshot.ts
25882
27073
  const ATOMIC_FINAL_SNAPSHOT_TYPES = /* @__PURE__ */ new Set([
@@ -26204,30 +27395,6 @@ async function createReplicationGroupFinalSnapshot(client, replicationGroupId, l
26204
27395
  const NESTED_STACK_RESOURCE_TYPE$1 = "AWS::CloudFormation::Stack";
26205
27396
  const nonEmptyString = (v) => typeof v === "string" && v.length > 0;
26206
27397
 
26207
- //#endregion
26208
- //#region src/deployment/producer-regions-scope.ts
26209
- const producerRegionsStore = new AsyncLocalStorage();
26210
- function withProducerRegions(evidence, fn) {
26211
- return producerRegionsStore.run(evidence, fn);
26212
- }
26213
- function getCurrentProducerRegions() {
26214
- return producerRegionsStore.getStore();
26215
- }
26216
- function inheritProducerRegions(own, inherited) {
26217
- const seen = /* @__PURE__ */ new Set();
26218
- const regions = [];
26219
- for (const region of [...own, ...inherited?.regions ?? []]) {
26220
- const canonical = canonicalizeRegion(region);
26221
- if (!canonical || seen.has(canonical)) continue;
26222
- seen.add(canonical);
26223
- regions.push(region);
26224
- }
26225
- return {
26226
- regions,
26227
- complete: inherited?.complete === true
26228
- };
26229
- }
26230
-
26231
27398
  //#endregion
26232
27399
  //#region src/deployment/rollback-executor/messages.ts
26233
27400
  function throwIfDeleteSkipped(result, logicalId, physicalId, duringClause) {
@@ -26371,6 +27538,271 @@ function retainedSurvivorMessages(logicalId, resourceType, survivorPhysicalId, s
26371
27538
  };
26372
27539
  }
26373
27540
 
27541
+ //#endregion
27542
+ //#region src/deployment/rollback-executor/names.ts
27543
+ function replayPrefixScope(input, logger, mask, restoring) {
27544
+ const choice = replayPrefixChoice(input);
27545
+ if (choice.kind === "not-applicable") return (fn) => fn();
27546
+ const setting = (skip) => skip ? "SKIPPED" : "KEPT";
27547
+ const subject = `${safe(input.logicalId)} (${safe(input.resourceType)})`;
27548
+ const declared = choice.declared;
27549
+ const secretDerived = declared !== void 0 && mask(declared) !== declared;
27550
+ const withheld = secretDerived || choice.kind === "unreproduced" && declared === void 0;
27551
+ const shown = (value) => displayIdent(mask(String(value)));
27552
+ const quoted = (value) => {
27553
+ const masked = mask(value);
27554
+ const rendered = displayIdent(masked);
27555
+ return rendered === masked ? `"${masked}"` : rendered;
27556
+ };
27557
+ if (choice.kind === "reproduced" && choice.skipPrefix !== choice.recorded) logger.info(mask(` Rollback: ${restoring ? "re-creating" : "reverting"} ${subject} under the user-supplied-name prefix setting that created ` + (withheld ? `it (its physical id is withheld, as its name is secret-derived): ` : `${shown(input.physicalId)} (`) + `stack-name prefix ${setting(choice.skipPrefix)}; the failed deploy ran with it ${setting(choice.recorded)}${withheld ? "" : ")"}`));
27558
+ else if (choice.kind === "unreproduced" && restoring) {
27559
+ const idUnreadable = typeof input.physicalId !== "string" || input.physicalId === "";
27560
+ const prop = safe(choice.property);
27561
+ const unreadable = declared === void 0 ? idUnreadable ? `its ${prop} or its physical id` : `its ${prop}` : idUnreadable ? `its physical id` : void 0;
27562
+ logger.warn(mask(` ⚠ ${subject}: cdkd cannot tell which user-supplied-name prefix setting created the old resource (` + (withheld ? `its physical id is withheld, as its name is secret-derived or unreadable` : shown(input.physicalId)) + `) — ` + (choice.names === void 0 ? unreadable !== void 0 ? `cdkd cannot read ${unreadable} to compare` : `cdkd cannot derive the names its ${prop} takes to compare` : secretDerived ? `its ${prop} is secret-derived, and neither name it derives matches` : `its ${prop} derives to ${quoted(choice.names.skipped)} (prefix skipped) or ${quoted(choice.names.kept)} (prefix kept), and it is neither`) + `; re-creating it with the stack-name prefix ${setting(choice.skipPrefix)}, as the failed deploy ran, so it may come back under a different physical name.`));
27563
+ }
27564
+ const skip = choice.skipPrefix;
27565
+ return (fn) => withSkipPrefix(skip, fn);
27566
+ }
27567
+ function createOpMasker(logger, secrets) {
27568
+ const base = createMaskedLogSinks(logger, (text) => maskSecretsInText(text, secrets));
27569
+ const pairs = [];
27570
+ let sinks = base;
27571
+ return {
27572
+ mask: (text) => typeof text === "string" ? sinks.mask(text) : text,
27573
+ addNamed: (record) => {
27574
+ pairs.push(...secretDerivedNamePairs(record));
27575
+ sinks = withDerivedNameMasks(logger, base, pairs);
27576
+ }
27577
+ };
27578
+ }
27579
+ const OTHER_SPELLED_NAME_KEYS = {
27580
+ "AWS::Cognito::UserPoolDomain": ["Domain"],
27581
+ "AWS::Cognito::UserPoolUser": ["Username"],
27582
+ "AWS::ECS::TaskDefinition": ["Family"],
27583
+ "AWS::ElastiCache::ReplicationGroup": ["ReplicationGroupId"],
27584
+ "AWS::ElastiCache::User": ["UserId"],
27585
+ "AWS::ElastiCache::UserGroup": ["UserGroupId"],
27586
+ "AWS::SES::EmailIdentity": ["EmailIdentity"]
27587
+ };
27588
+ const COMPOSITE_SCOPE_LAST = /^(?:REGIONAL|CLOUDFRONT|GLOBAL)$/;
27589
+ const COMPOSITE_POOL_FIRST = /^[a-z]{2}(?:-gov)?-[a-z]+-\d+_[A-Za-z0-9]+$/;
27590
+ function idNameSegments(id) {
27591
+ const segments = /* @__PURE__ */ new Set();
27592
+ const arn = /^arn:[^:]*:([^:]*):[^:]*:[^:]*:(.+)$/.exec(id);
27593
+ if (arn !== null) {
27594
+ const service = arn[1];
27595
+ const resource = arn[2];
27596
+ const lambda = service === "lambda" ? /^(?:function|layer):([^:]+)(?::([^:]+))?/.exec(resource) : null;
27597
+ if (lambda !== null) {
27598
+ segments.add(lambda[1]);
27599
+ const qualifier = lambda[2];
27600
+ if (qualifier !== void 0 && !/^\d+$/.test(qualifier)) segments.add(qualifier);
27601
+ } else {
27602
+ const parts = resource.split(/[/:]/).filter((part) => part !== "");
27603
+ let body = parts.length > 1 ? parts.slice(1) : parts;
27604
+ if (body.length > 1 && /^\d+$/.test(body[body.length - 1])) body = body.slice(0, -1);
27605
+ for (const part of body) {
27606
+ segments.add(part);
27607
+ if (service === "secretsmanager") segments.add(part.replace(/-[A-Za-z0-9]{6}$/, ""));
27608
+ }
27609
+ }
27610
+ }
27611
+ if (id.includes("/")) {
27612
+ const afterSlash = id.slice(id.lastIndexOf("/") + 1);
27613
+ segments.add(afterSlash);
27614
+ segments.add(afterSlash.replace(/:\d+$/, ""));
27615
+ }
27616
+ if (id.includes("|")) {
27617
+ const parts = id.split("|");
27618
+ parts.forEach((part, index) => {
27619
+ if (part === "") return;
27620
+ if (index === parts.length - 1 && parts.length > 1 && COMPOSITE_SCOPE_LAST.test(part)) return;
27621
+ if (index === 0 && parts.length > 1 && COMPOSITE_POOL_FIRST.test(part)) return;
27622
+ segments.add(part);
27623
+ });
27624
+ }
27625
+ return [...segments].filter((segment) => segment.length >= 4 && segment !== id);
27626
+ }
27627
+ function ownEntry(table, key) {
27628
+ return Object.hasOwn(table, key) ? table[key] : void 0;
27629
+ }
27630
+ function secretDerivedNamePairs(record) {
27631
+ const { resourceType, properties, logicalId } = record;
27632
+ if (typeof resourceType !== "string" || !isRestorableBag(properties)) return [];
27633
+ const rewritten = reverseReplacementRewrittenNameTypes();
27634
+ const named = /* @__PURE__ */ new Set();
27635
+ const primary = Object.hasOwn(rewritten, resourceType) ? rewritten[resourceType].property : explicitNamePropertyFor(resourceType);
27636
+ if (typeof primary === "string") named.add(primary);
27637
+ for (const key of Object.keys(properties)) if (/(?:Name|Identifier)$/.test(key)) named.add(key);
27638
+ for (const key of ownEntry(OTHER_SPELLED_NAME_KEYS, resourceType) ?? []) named.add(key);
27639
+ const idSpellings = record.physicalIds.filter((id) => typeof id === "string" && id !== "").flatMap((id) => [
27640
+ id,
27641
+ ...id.toLowerCase() === id || id.length < 4 ? [] : [id.toLowerCase()],
27642
+ finalSnapshotNamePrefix(id, resourceType),
27643
+ ...idNameSegments(id)
27644
+ ]);
27645
+ const pairs = [];
27646
+ for (const key of named) {
27647
+ if (!Object.hasOwn(properties, key)) continue;
27648
+ const value = properties[key];
27649
+ if (typeof value !== "string" || value === "") continue;
27650
+ const derived = key === primary && !value.includes("{{resolve:") && value !== "***" ? rewrittenNameSpellings(resourceType, value, logicalId) : [];
27651
+ for (const spelling of [...idSpellings, ...derived]) pairs.push([value, spelling]);
27652
+ }
27653
+ return pairs;
27654
+ }
27655
+ function addRecordNames(opMasker, op, current) {
27656
+ const { logicalId } = op;
27657
+ for (const properties of [op.properties, op.attemptedProperties]) opMasker.addNamed({
27658
+ resourceType: op.resourceType,
27659
+ properties,
27660
+ logicalId,
27661
+ physicalIds: [op.physicalId]
27662
+ });
27663
+ for (const record of [op.previousState, current]) {
27664
+ if (record === null || typeof record !== "object") continue;
27665
+ opMasker.addNamed({
27666
+ resourceType: record.resourceType ?? op.resourceType,
27667
+ properties: record.properties,
27668
+ logicalId,
27669
+ physicalIds: [record.physicalId]
27670
+ });
27671
+ }
27672
+ }
27673
+ const ABSENT_BASELINE_SKIP_CAUSE = "Its recorded previous state has no `properties` bag, so there is nothing to restore it to; the rollback left the resource exactly as it is.";
27674
+ function requireRestorableBaseline(bag, logger, { logicalId, consequence, remedy, retry }) {
27675
+ if (isRestorableBag(bag)) return true;
27676
+ if (bag === void 0) {
27677
+ logger.warn(` Rollback: Cannot restore ${shownLogicalId(logicalId)} \u2014 its recorded previous state has no \`properties\` bag, so there is nothing to restore it to. An empty desired state would ${consequence}. The resource is therefore left exactly as it is. ${remedy}`);
27678
+ return false;
27679
+ }
27680
+ const shape = bag === null ? "null" : Array.isArray(bag) ? "an array" : `a ${typeof bag}`;
27681
+ throw new CdkdError(`Cannot roll ${shownLogicalId(logicalId)} back: its recorded previous state has a \`properties\` field that is not a property bag (${shape}), so cdkd cannot tell what to restore it to. Replaying it would do one of two things, and cdkd does neither: send the malformed value to the provider as-is, or send an empty desired state (which would ${consequence}). The rollback JOURNAL record is kept: once that record holds a property bag again, ${retry}. Otherwise fix forward with \`cdkd deploy\`, or remove the stack with \`cdkd destroy\`.`, "ROLLBACK_UNUSABLE_BASELINE");
27682
+ }
27683
+ function isRestorableBag(bag) {
27684
+ return typeof bag === "object" && bag !== null && !Array.isArray(bag);
27685
+ }
27686
+ async function prepareCreateRollbackFinalSnapshot(op, provisionedBy, ctx, mask) {
27687
+ const { logicalId, resourceType } = op;
27688
+ const physicalId = op.physicalId;
27689
+ switch (finalSnapshotMechanism(resourceType, provisionedBy)) {
27690
+ case "atomic-delete-parameter": return buildFinalSnapshotIdentifier(physicalId, resourceType);
27691
+ case "pre-delete-snapshot":
27692
+ await createPreDeleteFinalSnapshot(resourceType, physicalId, logicalId, ctx.finalSnapshotClients ?? getAwsClients(), {
27693
+ info: (message) => ctx.logger.info(mask(message)),
27694
+ debug: (message) => ctx.logger.debug(mask(message))
27695
+ });
27696
+ return;
27697
+ case "refuse-cc-routed": throw ccRoutedFinalSnapshotError(logicalId, resourceType, SKIP_FINAL_SNAPSHOT_FLAG);
27698
+ case "refuse-unsupported-type": throw unsupportedFinalSnapshotError(logicalId, resourceType, SKIP_FINAL_SNAPSHOT_FLAG);
27699
+ }
27700
+ }
27701
+
27702
+ //#endregion
27703
+ //#region src/deployment/rollback-executor/replay-inline-policy-restore.ts
27704
+ async function restoreHeldInlinePolicies(writers, stateResources, stackName, ctx, result, options = {}) {
27705
+ for (const removal of writers.takeHeldRemovals(stateResources)) await restoreOne(removal, stateResources, stackName, ctx, result, options.refuseAll === true);
27706
+ }
27707
+ async function restoreOne({ kind, holders, unreadable, unsettled }, stateResources, stackName, ctx, result, refuseAll) {
27708
+ const { logger } = ctx;
27709
+ const ids = [...new Set(holders.map((h) => h.logicalId))].map((id) => safe(id)).join(", ");
27710
+ const lost = safeMsg`the ${kind} it is on lacks that inline policy until the resource is next updated, or ` + `'cdkd drift <stack> --revert' restores it`;
27711
+ if (refuseAll || unsettled.length > 0) {
27712
+ const pending = refuseAll ? ids : unsettled.map((id) => safe(id)).join(", ");
27713
+ logger.warn(safeMsg` Rollback: an inline policy this rollback removed is recorded by ${ids}, but the ` + safeMsg`rollback of ${pending} has not completed, so that record may be the failed ` + safeMsg`deploy's and cdkd did not put it back; ${lost}.`);
27714
+ result.warnings++;
27715
+ return;
27716
+ }
27717
+ if (unreadable.length > 0) {
27718
+ logger.warn(safeMsg` Rollback: an inline policy this rollback removed is recorded by ${ids}, and ` + safeMsg`${unreadable.map((id) => safe(id)).join(", ")} may record it too under a redacted ` + safeMsg`name, so cdkd did not put it back; ${lost}.`);
27719
+ result.warnings++;
27720
+ return;
27721
+ }
27722
+ const documents = holders.map((h) => serializedDocument(h.document));
27723
+ if (documents.some((d) => d === void 0)) {
27724
+ logger.warn(safeMsg` Rollback: an inline policy this rollback removed is still recorded by ${ids}, but its ` + safeMsg`recorded document is absent or redacted, so cdkd did not put it back; ${lost}.`);
27725
+ result.warnings++;
27726
+ return;
27727
+ }
27728
+ if (new Set(documents).size > 1) {
27729
+ logger.warn(safeMsg` Rollback: an inline policy this rollback removed is recorded by ${ids} with different ` + safeMsg`documents under one name on one ${kind}, so cdkd put neither back; ${lost}.`);
27730
+ result.warnings++;
27731
+ return;
27732
+ }
27733
+ const holder = holders[0];
27734
+ const secrets = /* @__PURE__ */ new Map();
27735
+ for (const h of holders) {
27736
+ const bag = ctx.logOnlyNeedlesFor?.(h.logicalId);
27737
+ if (bag) carryLogOnlyValues(bag, secrets);
27738
+ }
27739
+ const masker = createOpMasker(logger, secrets);
27740
+ for (const h of holders) {
27741
+ const record = stateResources[h.logicalId];
27742
+ addRecordNames(masker, {
27743
+ logicalId: h.logicalId,
27744
+ resourceType: record?.resourceType,
27745
+ physicalId: record?.physicalId
27746
+ }, record);
27747
+ }
27748
+ try {
27749
+ const { provider, provisionedBy } = ctx.providerRegistry.getProviderFor({
27750
+ resourceType: "AWS::IAM::Policy",
27751
+ provisionedBy: "sdk"
27752
+ });
27753
+ if (provisionedBy !== "sdk") throw new Error("AWS::IAM::Policy is not routed to its SDK provider");
27754
+ await provider.create(holder.logicalId, "AWS::IAM::Policy", {
27755
+ PolicyName: holder.policyName,
27756
+ PolicyDocument: holder.document,
27757
+ [POLICY_LIST_FIELDS[kind]]: [holder.principal]
27758
+ }, { maskSecrets: masker.mask });
27759
+ } catch (error) {
27760
+ logger.warn(maskedFailureText(safeMsg` Rollback: could not put back the inline policy ${ids} records on its ${kind} ` + safeMsg`(${lost}): `, error, masker.mask));
27761
+ result.warnings++;
27762
+ return;
27763
+ }
27764
+ logger.info(safeMsg` Rollback: put back the inline policy ${ids} records on its ${kind}`);
27765
+ const holderType = stateResources[holder.logicalId]?.resourceType;
27766
+ ctx.recordEvent?.({
27767
+ eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
27768
+ stackName,
27769
+ operation: "UPDATE",
27770
+ logicalId: holder.logicalId,
27771
+ ...typeof holderType === "string" && { resourceType: holderType },
27772
+ provisionedBy: "sdk",
27773
+ reason: `Put back the inline policy this resource records on its ${kind}, which the rollback had removed from it.`
27774
+ });
27775
+ }
27776
+ function serializedDocument(document) {
27777
+ if (typeof document === "string") return document.length > 0 && !isRedactedRecordedValue(document) ? document : void 0;
27778
+ if (document === null || typeof document !== "object" || Array.isArray(document)) return;
27779
+ return isRedactedRecordedValue(document) ? void 0 : JSON.stringify(document);
27780
+ }
27781
+
27782
+ //#endregion
27783
+ //#region src/deployment/producer-regions-scope.ts
27784
+ const producerRegionsStore = new AsyncLocalStorage();
27785
+ function withProducerRegions(evidence, fn) {
27786
+ return producerRegionsStore.run(evidence, fn);
27787
+ }
27788
+ function getCurrentProducerRegions() {
27789
+ return producerRegionsStore.getStore();
27790
+ }
27791
+ function inheritProducerRegions(own, inherited) {
27792
+ const seen = /* @__PURE__ */ new Set();
27793
+ const regions = [];
27794
+ for (const region of [...own, ...inherited?.regions ?? []]) {
27795
+ const canonical = canonicalizeRegion(region);
27796
+ if (!canonical || seen.has(canonical)) continue;
27797
+ seen.add(canonical);
27798
+ regions.push(region);
27799
+ }
27800
+ return {
27801
+ regions,
27802
+ complete: inherited?.complete === true
27803
+ };
27804
+ }
27805
+
26374
27806
  //#endregion
26375
27807
  //#region src/deployment/rollback-executor/replay-secrets.ts
26376
27808
  function replayProducerRegionEvidence(ctx) {
@@ -26590,7 +28022,7 @@ function classifyFailedOp(op, stateResources) {
26590
28022
  if (op.changeType === "CREATE") {
26591
28023
  if (!op.physicalId) return "skip-failed-unknown";
26592
28024
  if (!current) return "skip-failed-noop";
26593
- if (current.physicalId !== op.physicalId) return "skip-failed-noop";
28025
+ if (current.physicalId !== op.physicalId) return "skip-failed-mismatch";
26594
28026
  const policy = effectiveDeletionPolicy(current.resourceType, current.deletionPolicy, current.properties);
26595
28027
  if (policy === "Retain") return "orphan-failed-create-retain";
26596
28028
  if (policy === "Snapshot") return "delete-failed-create-with-final-snapshot";
@@ -26674,167 +28106,6 @@ function sortRollbackCreates(createOps, stateResources, logger) {
26674
28106
  return sorted;
26675
28107
  }
26676
28108
 
26677
- //#endregion
26678
- //#region src/deployment/rollback-executor/names.ts
26679
- function replayPrefixScope(input, logger, mask, restoring) {
26680
- const choice = replayPrefixChoice(input);
26681
- if (choice.kind === "not-applicable") return (fn) => fn();
26682
- const setting = (skip) => skip ? "SKIPPED" : "KEPT";
26683
- const subject = `${safe(input.logicalId)} (${safe(input.resourceType)})`;
26684
- const declared = choice.declared;
26685
- const secretDerived = declared !== void 0 && mask(declared) !== declared;
26686
- const withheld = secretDerived || choice.kind === "unreproduced" && declared === void 0;
26687
- const shown = (value) => displayIdent(mask(String(value)));
26688
- const quoted = (value) => {
26689
- const masked = mask(value);
26690
- const rendered = displayIdent(masked);
26691
- return rendered === masked ? `"${masked}"` : rendered;
26692
- };
26693
- if (choice.kind === "reproduced" && choice.skipPrefix !== choice.recorded) logger.info(mask(` Rollback: ${restoring ? "re-creating" : "reverting"} ${subject} under the user-supplied-name prefix setting that created ` + (withheld ? `it (its physical id is withheld, as its name is secret-derived): ` : `${shown(input.physicalId)} (`) + `stack-name prefix ${setting(choice.skipPrefix)}; the failed deploy ran with it ${setting(choice.recorded)}${withheld ? "" : ")"}`));
26694
- else if (choice.kind === "unreproduced" && restoring) {
26695
- const idUnreadable = typeof input.physicalId !== "string" || input.physicalId === "";
26696
- const prop = safe(choice.property);
26697
- const unreadable = declared === void 0 ? idUnreadable ? `its ${prop} or its physical id` : `its ${prop}` : idUnreadable ? `its physical id` : void 0;
26698
- logger.warn(mask(` ⚠ ${subject}: cdkd cannot tell which user-supplied-name prefix setting created the old resource (` + (withheld ? `its physical id is withheld, as its name is secret-derived or unreadable` : shown(input.physicalId)) + `) — ` + (choice.names === void 0 ? unreadable !== void 0 ? `cdkd cannot read ${unreadable} to compare` : `cdkd cannot derive the names its ${prop} takes to compare` : secretDerived ? `its ${prop} is secret-derived, and neither name it derives matches` : `its ${prop} derives to ${quoted(choice.names.skipped)} (prefix skipped) or ${quoted(choice.names.kept)} (prefix kept), and it is neither`) + `; re-creating it with the stack-name prefix ${setting(choice.skipPrefix)}, as the failed deploy ran, so it may come back under a different physical name.`));
26699
- }
26700
- const skip = choice.skipPrefix;
26701
- return (fn) => withSkipPrefix(skip, fn);
26702
- }
26703
- function createOpMasker(logger, secrets) {
26704
- const base = createMaskedLogSinks(logger, (text) => maskSecretsInText(text, secrets));
26705
- const pairs = [];
26706
- let sinks = base;
26707
- return {
26708
- mask: (text) => typeof text === "string" ? sinks.mask(text) : text,
26709
- addNamed: (record) => {
26710
- pairs.push(...secretDerivedNamePairs(record));
26711
- sinks = withDerivedNameMasks(logger, base, pairs);
26712
- }
26713
- };
26714
- }
26715
- const OTHER_SPELLED_NAME_KEYS = {
26716
- "AWS::Cognito::UserPoolDomain": ["Domain"],
26717
- "AWS::Cognito::UserPoolUser": ["Username"],
26718
- "AWS::ECS::TaskDefinition": ["Family"],
26719
- "AWS::ElastiCache::ReplicationGroup": ["ReplicationGroupId"],
26720
- "AWS::ElastiCache::User": ["UserId"],
26721
- "AWS::ElastiCache::UserGroup": ["UserGroupId"],
26722
- "AWS::SES::EmailIdentity": ["EmailIdentity"]
26723
- };
26724
- const COMPOSITE_SCOPE_LAST = /^(?:REGIONAL|CLOUDFRONT|GLOBAL)$/;
26725
- const COMPOSITE_POOL_FIRST = /^[a-z]{2}(?:-gov)?-[a-z]+-\d+_[A-Za-z0-9]+$/;
26726
- function idNameSegments(id) {
26727
- const segments = /* @__PURE__ */ new Set();
26728
- const arn = /^arn:[^:]*:([^:]*):[^:]*:[^:]*:(.+)$/.exec(id);
26729
- if (arn !== null) {
26730
- const service = arn[1];
26731
- const resource = arn[2];
26732
- const lambda = service === "lambda" ? /^(?:function|layer):([^:]+)(?::([^:]+))?/.exec(resource) : null;
26733
- if (lambda !== null) {
26734
- segments.add(lambda[1]);
26735
- const qualifier = lambda[2];
26736
- if (qualifier !== void 0 && !/^\d+$/.test(qualifier)) segments.add(qualifier);
26737
- } else {
26738
- const parts = resource.split(/[/:]/).filter((part) => part !== "");
26739
- let body = parts.length > 1 ? parts.slice(1) : parts;
26740
- if (body.length > 1 && /^\d+$/.test(body[body.length - 1])) body = body.slice(0, -1);
26741
- for (const part of body) {
26742
- segments.add(part);
26743
- if (service === "secretsmanager") segments.add(part.replace(/-[A-Za-z0-9]{6}$/, ""));
26744
- }
26745
- }
26746
- }
26747
- if (id.includes("/")) {
26748
- const afterSlash = id.slice(id.lastIndexOf("/") + 1);
26749
- segments.add(afterSlash);
26750
- segments.add(afterSlash.replace(/:\d+$/, ""));
26751
- }
26752
- if (id.includes("|")) {
26753
- const parts = id.split("|");
26754
- parts.forEach((part, index) => {
26755
- if (part === "") return;
26756
- if (index === parts.length - 1 && parts.length > 1 && COMPOSITE_SCOPE_LAST.test(part)) return;
26757
- if (index === 0 && parts.length > 1 && COMPOSITE_POOL_FIRST.test(part)) return;
26758
- segments.add(part);
26759
- });
26760
- }
26761
- return [...segments].filter((segment) => segment.length >= 4 && segment !== id);
26762
- }
26763
- function ownEntry(table, key) {
26764
- return Object.hasOwn(table, key) ? table[key] : void 0;
26765
- }
26766
- function secretDerivedNamePairs(record) {
26767
- const { resourceType, properties, logicalId } = record;
26768
- if (typeof resourceType !== "string" || !isRestorableBag(properties)) return [];
26769
- const rewritten = reverseReplacementRewrittenNameTypes();
26770
- const named = /* @__PURE__ */ new Set();
26771
- const primary = Object.hasOwn(rewritten, resourceType) ? rewritten[resourceType].property : explicitNamePropertyFor(resourceType);
26772
- if (typeof primary === "string") named.add(primary);
26773
- for (const key of Object.keys(properties)) if (/(?:Name|Identifier)$/.test(key)) named.add(key);
26774
- for (const key of ownEntry(OTHER_SPELLED_NAME_KEYS, resourceType) ?? []) named.add(key);
26775
- const idSpellings = record.physicalIds.filter((id) => typeof id === "string" && id !== "").flatMap((id) => [
26776
- id,
26777
- ...id.toLowerCase() === id || id.length < 4 ? [] : [id.toLowerCase()],
26778
- finalSnapshotNamePrefix(id, resourceType),
26779
- ...idNameSegments(id)
26780
- ]);
26781
- const pairs = [];
26782
- for (const key of named) {
26783
- if (!Object.hasOwn(properties, key)) continue;
26784
- const value = properties[key];
26785
- if (typeof value !== "string" || value === "") continue;
26786
- const derived = key === primary && !value.includes("{{resolve:") && value !== "***" ? rewrittenNameSpellings(resourceType, value, logicalId) : [];
26787
- for (const spelling of [...idSpellings, ...derived]) pairs.push([value, spelling]);
26788
- }
26789
- return pairs;
26790
- }
26791
- function addRecordNames(opMasker, op, current) {
26792
- const { logicalId } = op;
26793
- for (const properties of [op.properties, op.attemptedProperties]) opMasker.addNamed({
26794
- resourceType: op.resourceType,
26795
- properties,
26796
- logicalId,
26797
- physicalIds: [op.physicalId]
26798
- });
26799
- for (const record of [op.previousState, current]) {
26800
- if (record === null || typeof record !== "object") continue;
26801
- opMasker.addNamed({
26802
- resourceType: record.resourceType ?? op.resourceType,
26803
- properties: record.properties,
26804
- logicalId,
26805
- physicalIds: [record.physicalId]
26806
- });
26807
- }
26808
- }
26809
- const ABSENT_BASELINE_SKIP_CAUSE = "Its recorded previous state has no `properties` bag, so there is nothing to restore it to; the rollback left the resource exactly as it is.";
26810
- function requireRestorableBaseline(bag, logger, { logicalId, consequence, remedy, retry }) {
26811
- if (isRestorableBag(bag)) return true;
26812
- if (bag === void 0) {
26813
- logger.warn(` Rollback: Cannot restore ${shownLogicalId(logicalId)} \u2014 its recorded previous state has no \`properties\` bag, so there is nothing to restore it to. An empty desired state would ${consequence}. The resource is therefore left exactly as it is. ${remedy}`);
26814
- return false;
26815
- }
26816
- const shape = bag === null ? "null" : Array.isArray(bag) ? "an array" : `a ${typeof bag}`;
26817
- throw new CdkdError(`Cannot roll ${shownLogicalId(logicalId)} back: its recorded previous state has a \`properties\` field that is not a property bag (${shape}), so cdkd cannot tell what to restore it to. Replaying it would do one of two things, and cdkd does neither: send the malformed value to the provider as-is, or send an empty desired state (which would ${consequence}). The rollback JOURNAL record is kept: once that record holds a property bag again, ${retry}. Otherwise fix forward with \`cdkd deploy\`, or remove the stack with \`cdkd destroy\`.`, "ROLLBACK_UNUSABLE_BASELINE");
26818
- }
26819
- function isRestorableBag(bag) {
26820
- return typeof bag === "object" && bag !== null && !Array.isArray(bag);
26821
- }
26822
- async function prepareCreateRollbackFinalSnapshot(op, provisionedBy, ctx, mask) {
26823
- const { logicalId, resourceType } = op;
26824
- const physicalId = op.physicalId;
26825
- switch (finalSnapshotMechanism(resourceType, provisionedBy)) {
26826
- case "atomic-delete-parameter": return buildFinalSnapshotIdentifier(physicalId, resourceType);
26827
- case "pre-delete-snapshot":
26828
- await createPreDeleteFinalSnapshot(resourceType, physicalId, logicalId, ctx.finalSnapshotClients ?? getAwsClients(), {
26829
- info: (message) => ctx.logger.info(mask(message)),
26830
- debug: (message) => ctx.logger.debug(mask(message))
26831
- });
26832
- return;
26833
- case "refuse-cc-routed": throw ccRoutedFinalSnapshotError(logicalId, resourceType, SKIP_FINAL_SNAPSHOT_FLAG);
26834
- case "refuse-unsupported-type": throw unsupportedFinalSnapshotError(logicalId, resourceType, SKIP_FINAL_SNAPSHOT_FLAG);
26835
- }
26836
- }
26837
-
26838
28109
  //#endregion
26839
28110
  //#region src/deployment/rollback-executor/replay-props.ts
26840
28111
  async function resolveReplayProps(props, resolvers, secrets, execCtx, logicalId) {
@@ -27410,6 +28681,7 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
27410
28681
  };
27411
28682
  if (operations.length === 0) {
27412
28683
  ctx.logger.info("No completed operations to roll back.");
28684
+ await restoreHeldInlinePolicies(inlinePolicyWriters, stateResources, stackName, ctx, result);
27413
28685
  return result;
27414
28686
  }
27415
28687
  ctx.logger.info(`Rolling back ${operations.length} completed operation(s)...`);
@@ -27418,6 +28690,7 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
27418
28690
  stackName
27419
28691
  });
27420
28692
  const resolver = new ReplayResolvers(ctx.region);
28693
+ inlinePolicyWriters.notePending(operations);
27421
28694
  const { createOps, otherOps } = partitionOps(operations);
27422
28695
  for (let i = otherOps.length - 1; i >= 0; i--) {
27423
28696
  if (options.isInterrupted?.()) {
@@ -27436,6 +28709,7 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
27436
28709
  await replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.onOrphan, inlinePolicyWriters, options.afterOp, options.isInterrupted);
27437
28710
  }
27438
28711
  }
28712
+ await restoreHeldInlinePolicies(inlinePolicyWriters, stateResources, stackName, ctx, result);
27439
28713
  ctx.logger.info("Rollback completed. Some resources may remain if deletion failed.");
27440
28714
  ctx.recordEvent?.({
27441
28715
  eventType: "ROLLBACK_FINISHED",
@@ -27470,6 +28744,7 @@ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphan
27470
28744
  mask,
27471
28745
  createRollbackRoute: void 0
27472
28746
  };
28747
+ const recordBefore = ownRecord(stateResources, op.logicalId);
27473
28748
  try {
27474
28749
  addRecordNames(opMasker, op, stateResources[op.logicalId]);
27475
28750
  switch (action) {
@@ -27514,8 +28789,13 @@ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphan
27514
28789
  ...failedRoute && { provisionedBy: failedRoute },
27515
28790
  error: maskedRollbackEventError(rollbackError, mask)
27516
28791
  });
28792
+ } finally {
28793
+ inlinePolicyWriters.noteOutcome(op, action === "skip-already-done" || ownRecord(stateResources, op.logicalId) !== recordBefore);
27517
28794
  }
27518
28795
  }
28796
+ function ownRecord(stateResources, logicalId) {
28797
+ return Object.hasOwn(stateResources, logicalId) ? stateResources[logicalId] : void 0;
28798
+ }
27519
28799
  async function replayFailedOperationsUnbound(failedOps, stateResources, stackName, ctx, options = {}) {
27520
28800
  const inlinePolicyWriters = options.inlinePolicyWriters ?? new RollbackInlinePolicyWriters();
27521
28801
  const result = {
@@ -27552,12 +28832,17 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
27552
28832
  mask
27553
28833
  };
27554
28834
  let createRollbackRoute;
28835
+ const recordBefore = ownRecord(stateResources, op.logicalId);
27555
28836
  try {
27556
28837
  addRecordNames(opMasker, op, stateResources[op.logicalId]);
27557
28838
  switch (action) {
27558
28839
  case "skip-failed-noop":
27559
28840
  logger.info(` Rollback: failed ${safe(op.changeType)} of ${safe(op.logicalId)} (${safe(op.resourceType)}) left nothing to revert, skipping`);
27560
28841
  break;
28842
+ case "skip-failed-mismatch":
28843
+ 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`);
28844
+ 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.");
28845
+ break;
27561
28846
  case "skip-failed-unknown":
27562
28847
  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`);
27563
28848
  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.");
@@ -27720,7 +29005,9 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
27720
29005
  error: maskedRollbackEventError(revertError, mask)
27721
29006
  });
27722
29007
  }
29008
+ inlinePolicyWriters.noteOutcome(op, action === "skip-failed-noop" || action === "skip-failed-mismatch" || ownRecord(stateResources, op.logicalId) !== recordBefore);
27723
29009
  }
29010
+ if (result.interrupted) await restoreHeldInlinePolicies(inlinePolicyWriters, stateResources, stackName, ctx, result, { refuseAll: true });
27724
29011
  if (emitEnvelope) ctx.recordEvent?.({
27725
29012
  eventType: "ROLLBACK_FINISHED",
27726
29013
  stackName
@@ -27763,7 +29050,7 @@ async function collectNestedChildUnaddressed(fn) {
27763
29050
  //#endregion
27764
29051
  //#region src/deployment/nested-child-journal.ts
27765
29052
  const NESTED_PENDING_PARENT_REASON = "nested-pending-parent";
27766
- const NESTED_STACK_TYPE = "AWS::CloudFormation::Stack";
29053
+ const NESTED_STACK_TYPE$1 = "AWS::CloudFormation::Stack";
27767
29054
  const MAX_NESTED_WALK_DEPTH = 32;
27768
29055
  function nestedChildStackName(parentStackName, logicalId) {
27769
29056
  return `${parentStackName}~${logicalId}`;
@@ -27780,8 +29067,46 @@ function nestedPendingSnapshot(state) {
27780
29067
  }
27781
29068
  };
27782
29069
  }
29070
+ function displacedPhysicalIdShown(op, logger, physicalId = journalOpPhysicalId(op)) {
29071
+ if (physicalId === void 0) return void 0;
29072
+ const masker = createOpMasker(logger, /* @__PURE__ */ new Map());
29073
+ for (const properties of [
29074
+ op.properties,
29075
+ op.attemptedProperties,
29076
+ op.previousState?.properties
29077
+ ]) {
29078
+ if (properties === void 0) continue;
29079
+ masker.addNamed({
29080
+ resourceType: op.resourceType,
29081
+ properties,
29082
+ logicalId: op.logicalId,
29083
+ physicalIds: [physicalId]
29084
+ });
29085
+ }
29086
+ return displaySafe(String(masker.mask(physicalId)));
29087
+ }
29088
+ function displacedOpClause(op, marks, logger) {
29089
+ const retainedOld = retainedOldPhysicalId(op);
29090
+ if (retainedOld !== void 0 && marks.some((m) => isMarkFor(m, op))) {
29091
+ const shownOld = displacedPhysicalIdShown(op, logger, retainedOld);
29092
+ 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`;
29093
+ }
29094
+ const shownId = displacedPhysicalIdShown(op, logger);
29095
+ 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";
29096
+ }
29097
+ function recordDisplacedSkips(recordEvent, stackName, ops) {
29098
+ for (const op of ops) recordEvent?.({
29099
+ eventType: "ROLLBACK_RESOURCE_SKIPPED",
29100
+ stackName,
29101
+ operation: op.changeType,
29102
+ logicalId: op.logicalId,
29103
+ resourceType: op.resourceType,
29104
+ ...op.provisionedBy && { provisionedBy: op.provisionedBy },
29105
+ 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"
29106
+ });
29107
+ }
27783
29108
  function revertedNestedRowIds(ops) {
27784
- return ops.filter((op) => op.resourceType === NESTED_STACK_TYPE && op.changeType === "UPDATE").map((op) => op.logicalId);
29109
+ return ops.filter((op) => op.resourceType === NESTED_STACK_TYPE$1 && op.changeType === "UPDATE").map((op) => op.logicalId);
27785
29110
  }
27786
29111
  const revertRunStorage = new AsyncLocalStorage();
27787
29112
  function withNestedRevertRun(runId, fn) {
@@ -27807,7 +29132,7 @@ async function dropNestedChildJournals(args) {
27807
29132
  if (!isPlainRecord(resources)) return;
27808
29133
  if (depthExceeded(depth, parentStackName, logger)) return;
27809
29134
  for (const [logicalId, record] of Object.entries(resources)) {
27810
- if (!isPlainRecord(record) || record["resourceType"] !== NESTED_STACK_TYPE) continue;
29135
+ if (!isPlainRecord(record) || record["resourceType"] !== NESTED_STACK_TYPE$1) continue;
27811
29136
  const child = nestedChildStackName(parentStackName, logicalId);
27812
29137
  try {
27813
29138
  const data = await stateBackend.getState(child, region);
@@ -27965,8 +29290,9 @@ async function revertNestedChildFromJournal(args) {
27965
29290
  for (let s = segments.length - 1; s >= 0; s--) {
27966
29291
  const segment = segments[s];
27967
29292
  const skipPrefix = segment.skipPrefix ?? getCurrentSkipPrefix();
29293
+ const split = splitImportedOps(segment.operations, segment);
27968
29294
  const result = await withNestedStackContext(childCtx, () => withSkipPrefix(skipPrefix, () => withStackName(childStackName, () => withCreateTokenLedger(ledgerForStack(ctx.stateBackend, childStackName, region), () => withNestedRevertRun(runId, async (inner) => {
27969
- const replayed = await replayRollback(segment.operations, stateResources, childStackName, execCtx, {
29295
+ const replayed = await replayRollback(split.replay, stateResources, childStackName, execCtx, {
27970
29296
  afterOp: save,
27971
29297
  onOrphan: (record) => mintedOrphans.push(record),
27972
29298
  inlinePolicyWriters
@@ -27978,7 +29304,9 @@ async function revertNestedChildFromJournal(args) {
27978
29304
  };
27979
29305
  })))));
27980
29306
  failures += result.failures;
27981
- warnings += result.warnings;
29307
+ warnings += result.warnings + split.displaced.length;
29308
+ recordDisplacedSkips(execCtx.recordEvent, childStackName, split.displaced);
29309
+ 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");
27982
29310
  }
27983
29311
  restoring = failures === 0;
27984
29312
  await save();
@@ -29264,9 +30592,9 @@ function extractAllDependencies(template, logicalId) {
29264
30592
  return deps.length > 0 ? deps : void 0;
29265
30593
  }
29266
30594
  function propertiesToRecord(desiredProperties, result, resourceType, provisionedBy) {
29267
- if (result.effectiveProperties) return provisionedBy === "sdk" ? withoutSilentDropProperties(resourceType, result.effectiveProperties) : result.effectiveProperties;
30595
+ if (result.effectiveProperties) return markWrittenFromDeployedTemplate(provisionedBy === "sdk" ? withoutSilentDropProperties(resourceType, result.effectiveProperties) : result.effectiveProperties);
29268
30596
  const written = provisionedBy === "sdk" ? withoutSilentDropProperties(resourceType, desiredProperties) : desiredProperties;
29269
- return markSameGenerationBag(written);
30597
+ return markWrittenFromDeployedTemplate(markSameGenerationBag(written));
29270
30598
  }
29271
30599
  function extractTemplateAttributes(template, logicalId) {
29272
30600
  const resource = template?.Resources?.[logicalId];
@@ -29383,8 +30711,15 @@ async function provisionCreate(logicalId, change, stateResources, stackName, tem
29383
30711
  const resolvedProps = await this.resolver.resolve(desiredProps, context);
29384
30712
  this.refuseRedactedAttributeReads(logicalId, resourceType, context);
29385
30713
  this.perResourceTemplateProps.set(logicalId, desiredProps);
30714
+ const fingerprintSources = template && this.maskedInputSources(template, stateResources, conditions, stackName);
30715
+ if (fingerprintSources !== void 0) this.perResourceInputFingerprints.set(logicalId, await maskedInputFingerprintsFor(possiblyMaskedKeys(resolvedProps, [
30716
+ context.recordedSecretValues,
30717
+ this.fingerprintNoEchoValues,
30718
+ this.options.inheritedSecrets
30719
+ ]), inputFingerprinter(desiredProps, fingerprintSources)));
29386
30720
  this.perResourceResolvedType.set(logicalId, resourceType);
29387
30721
  const createSecrets = context.recordedSecretValues ?? /* @__PURE__ */ new Map();
30722
+ if (fingerprintSources !== void 0 && resourceType === "AWS::CloudFormation::Stack") recordPassedParameterClasses(createSecrets, await classifyPassedParameters(desiredProps["Parameters"], fingerprintSources));
29388
30723
  recordNestedStackParameterExpressions(createSecrets, resourceType, resolvedProps, desiredProps);
29389
30724
  this.auditResolvedAssetReferences(logicalId, resourceType, resolvedProps);
29390
30725
  this.attemptedResolvedProps.set(logicalId, resolvedProps);
@@ -32276,12 +33611,22 @@ async function provisionUpdate(logicalId, change, stateResources, stackName, tem
32276
33611
  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;
32277
33612
  const lostWithParent = lostChild?.mode === "recreate" ? lostChild.parent : void 0;
32278
33613
  const suppliesFreshMaskOnlyValue = carriesFreshNoEchoValue(resolvedProps, updateSecrets);
33614
+ const fingerprintSources = template && this.maskedInputSources(template, stateResources, conditions, stackName);
33615
+ const fingerprints = fingerprintSources && inputFingerprinter(desiredProps, fingerprintSources);
33616
+ const movedMasked = new Set(await movedMaskedProperties(currentResource, desiredProps, fingerprints));
33617
+ if (fingerprints !== void 0) this.perResourceInputFingerprints.set(logicalId, await maskedInputFingerprintsFor(possiblyMaskedKeys(resolvedProps, [
33618
+ updateSecrets,
33619
+ this.fingerprintNoEchoValues,
33620
+ this.options.inheritedSecrets
33621
+ ]), fingerprints));
33622
+ if (fingerprintSources !== void 0 && resourceType === "AWS::CloudFormation::Stack") recordPassedParameterClasses(updateSecrets, await classifyPassedParameters(desiredProps["Parameters"], fingerprintSources));
32279
33623
  const desiredForSkipCheck = redactSecretsForState(markSameGenerationBag({ ...resolvedProps }), updateSecrets, desiredProps);
32280
33624
  const allowedSilentDrops = this.providerRegistry.getAllowedUnsupportedProperties?.();
32281
33625
  const desiredForSkipCheckAsWritten = currentResource.provisionedBy !== "cc-api" && allowedSilentDrops ? withoutAcceptedSilentDropProperties(resourceType, desiredForSkipCheck, allowedSilentDrops, currentResource.properties) : desiredForSkipCheck;
32282
33626
  const allowedForRecord = allowedSilentDrops ?? /* @__PURE__ */ new Set();
32283
33627
  const createOnlyEvidence = acceptedCreateOnlyDropsOf(currentResource);
32284
33628
  const currentPropsAsWritten = currentResource.provisionedBy === "cc-api" ? currentProps : withoutUnwrittenSilentDropProperties(resourceType, currentProps, desiredForSkipCheck, allowedForRecord, createOnlyEvidence);
33629
+ const recordMatchesDesired = movedMasked.size === 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten);
32285
33630
  const applyAttributeOnlyUpdate = (attributeChanges) => {
32286
33631
  const attrSummary = attributeChanges.map((a) => `${a.attribute}: ${a.oldValue ?? "(unset)"} → ${a.newValue ?? "(unset)"}`).join(", ");
32287
33632
  this.logger.info(safeMsg` ↻ ${logicalId} (${resourceType}) attribute update: ${attrSummary}`);
@@ -32295,7 +33640,7 @@ async function provisionUpdate(logicalId, change, stateResources, stackName, tem
32295
33640
  renderer.removeTask(logicalId);
32296
33641
  this.logger.info(safeMsg`${attrPrefix}${formatResourceLine("updated", logicalId, resourceType, "updated (metadata)")}`);
32297
33642
  };
32298
- if (!typeChanged && !suppliesFreshMaskOnlyValue && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten)) {
33643
+ if (!typeChanged && !suppliesFreshMaskOnlyValue && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && recordMatchesDesired) {
32299
33644
  if (change.attributeChanges && change.attributeChanges.length > 0) {
32300
33645
  applyAttributeOnlyUpdate(change.attributeChanges);
32301
33646
  return;
@@ -32320,7 +33665,7 @@ async function provisionUpdate(logicalId, change, stateResources, stackName, tem
32320
33665
  lowered.push(pc);
32321
33666
  continue;
32322
33667
  }
32323
- const moved = keyOrderFreeJson(desiredForSkipCheckAsWritten[pc.path]) !== keyOrderFreeJson(currentPropsAsWritten[pc.path]);
33668
+ const moved = movedMasked.has(pc.path) || keyOrderFreeJson(desiredForSkipCheckAsWritten[pc.path]) !== keyOrderFreeJson(currentPropsAsWritten[pc.path]);
32324
33669
  const conditionalVerdict = moved && !typeChanged && isReplacementCeiling(pc) ? this.diffCalculator.conditionalReplacementVerdict?.(resourceType, pc.path, currentPropsAsWritten[pc.path], desiredForSkipCheckAsWritten[pc.path]) : void 0;
32325
33670
  if (moved && conditionalVerdict !== false) {
32326
33671
  lowered.push(pc);
@@ -32352,7 +33697,7 @@ async function provisionUpdate(logicalId, change, stateResources, stackName, tem
32352
33697
  }
32353
33698
  change.propertyChanges = lowered;
32354
33699
  }
32355
- if (noEchoHeldPaths.size > 0 && !typeChanged && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten) && Object.entries(resolvedProps).every(([key, value]) => noEchoHeldPaths.has(key) || freshNoEchoLeafPositions(value, updateSecrets).length === 0)) {
33700
+ if (noEchoHeldPaths.size > 0 && !typeChanged && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && recordMatchesDesired && Object.entries(resolvedProps).every(([key, value]) => noEchoHeldPaths.has(key) || freshNoEchoLeafPositions(value, updateSecrets).length === 0)) {
32356
33701
  this.logger.debug(safeMsg`Skipping ${logicalId}: AWS already holds every NoEcho value it carries, and nothing else changed`);
32357
33702
  this.attemptedResolvedProps.delete(logicalId);
32358
33703
  if (change.attributeChanges && change.attributeChanges.length > 0) {
@@ -34014,6 +35359,184 @@ function conditionVerdictRecordsEqual(a, b) {
34014
35359
  return names.every((name) => Object.hasOwn(right, name) && left[name].verdict === right[name].verdict && left[name].fingerprint === right[name].fingerprint);
34015
35360
  }
34016
35361
 
35362
+ //#endregion
35363
+ //#region src/utils/nested-template-cycle.ts
35364
+ const NESTED_STACK_TYPE = "AWS::CloudFormation::Stack";
35365
+ function isAbsoluteAssetPath(p) {
35366
+ return path.isAbsolute(p) || p.startsWith("/");
35367
+ }
35368
+ function templateIdentity(templatePath) {
35369
+ const dir = path.dirname(templatePath);
35370
+ let realDir;
35371
+ try {
35372
+ realDir = fs.realpathSync.native(dir);
35373
+ } catch {
35374
+ realDir = path.resolve(dir);
35375
+ }
35376
+ return path.join(realDir, path.basename(templatePath));
35377
+ }
35378
+ function listNestedTemplateRows(template) {
35379
+ if (template === null || typeof template !== "object") return [];
35380
+ const resources = template.Resources;
35381
+ if (resources === null || resources === void 0) return [];
35382
+ const rows = [];
35383
+ for (const [logicalId, resource] of Object.entries(resources)) {
35384
+ const row = resource;
35385
+ if (row?.Type !== NESTED_STACK_TYPE) continue;
35386
+ const assetPath = row.Metadata?.["aws:asset:path"];
35387
+ if (typeof assetPath !== "string" || assetPath.length === 0) continue;
35388
+ rows.push({
35389
+ logicalId,
35390
+ assetPath
35391
+ });
35392
+ }
35393
+ return rows;
35394
+ }
35395
+ function readNestedRows(templatePath) {
35396
+ let parsed;
35397
+ try {
35398
+ parsed = JSON.parse(fs.readFileSync(templatePath, "utf-8"));
35399
+ } catch {
35400
+ return;
35401
+ }
35402
+ return listNestedTemplateRows(parsed);
35403
+ }
35404
+ const MAX_NESTING_DEPTH = 512;
35405
+ const MAX_ROWS_FOLLOWED = 1e4;
35406
+ function findNestedTemplateTreeDefect(nestedTemplates, ancestorTemplatePaths = []) {
35407
+ const onChain = /* @__PURE__ */ new Set();
35408
+ for (const p of ancestorTemplatePaths) onChain.add(templateIdentity(p));
35409
+ const clean = /* @__PURE__ */ new Set();
35410
+ const chain = [];
35411
+ let rowsFollowed = 0;
35412
+ const visit = (logicalId, templatePath) => {
35413
+ if (typeof templatePath !== "string") return void 0;
35414
+ const identity = templateIdentity(templatePath);
35415
+ const lexical = path.resolve(templatePath);
35416
+ chain.push({
35417
+ logicalId,
35418
+ templatePath: identity
35419
+ });
35420
+ try {
35421
+ if (onChain.has(identity)) return {
35422
+ kind: "cycle",
35423
+ chain: [...chain]
35424
+ };
35425
+ if (chain.length > 512) return {
35426
+ kind: "too-deep",
35427
+ chain: [...chain]
35428
+ };
35429
+ if (++rowsFollowed > 1e4) return {
35430
+ kind: "too-large",
35431
+ chain: [...chain]
35432
+ };
35433
+ if (clean.has(lexical)) return void 0;
35434
+ const rows = readNestedRows(templatePath);
35435
+ if (rows === void 0) return void 0;
35436
+ onChain.add(identity);
35437
+ try {
35438
+ const dir = path.dirname(templatePath);
35439
+ for (const row of rows) {
35440
+ if (isAbsoluteAssetPath(row.assetPath)) return {
35441
+ kind: "absolute-path",
35442
+ chain: [...chain],
35443
+ logicalId: row.logicalId,
35444
+ assetPath: row.assetPath
35445
+ };
35446
+ const resolved = resolveAssemblyPath(dir, row.assetPath);
35447
+ if (!resolved.contained) return {
35448
+ kind: "escaping-path",
35449
+ chain: [...chain],
35450
+ logicalId: row.logicalId,
35451
+ assetPath: row.assetPath,
35452
+ escape: resolved,
35453
+ dir
35454
+ };
35455
+ const defect = visit(row.logicalId, resolved.path);
35456
+ if (defect) return defect;
35457
+ }
35458
+ } finally {
35459
+ onChain.delete(identity);
35460
+ }
35461
+ clean.add(lexical);
35462
+ return;
35463
+ } finally {
35464
+ chain.pop();
35465
+ }
35466
+ };
35467
+ for (const [logicalId, templatePath] of Object.entries(nestedTemplates)) {
35468
+ const defect = visit(logicalId, templatePath);
35469
+ if (defect) return defect;
35470
+ }
35471
+ }
35472
+ const MAX_RENDERED_HOPS = 8;
35473
+ function renderChain(chain) {
35474
+ const hop = (h) => `${displayIdent(h.logicalId)} (${displayAssemblyPath(h.templatePath)})`;
35475
+ if (chain.length <= MAX_RENDERED_HOPS) return chain.map(hop).join(" then ");
35476
+ const keep = MAX_RENDERED_HOPS / 2;
35477
+ return [
35478
+ ...chain.slice(0, keep).map(hop),
35479
+ `... ${chain.length - 8} more ...`,
35480
+ ...chain.slice(-4).map(hop)
35481
+ ].join(" then ");
35482
+ }
35483
+ function renderNestedTemplateTreeDefect(defect, stackName, action) {
35484
+ 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}.`;
35485
+ const owner = (chain) => {
35486
+ const ids = chain.slice(0, -1).map((h) => h.logicalId);
35487
+ const keep = MAX_RENDERED_HOPS / 2;
35488
+ if (ids.length <= MAX_RENDERED_HOPS) return displayStackName([stackName, ...ids].join("~"));
35489
+ const head = displayStackName([stackName, ...ids.slice(0, keep)].join("~"));
35490
+ const tail = displayStackName(ids.slice(-4).join("~"));
35491
+ return `${head}~...${ids.length - 8} more...~${tail}`;
35492
+ };
35493
+ if (defect.kind === "cycle") {
35494
+ const closing = defect.chain[defect.chain.length - 1];
35495
+ 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}`;
35496
+ }
35497
+ 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}.`;
35498
+ 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}`;
35499
+ 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)}`;
35500
+ 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}`;
35501
+ }
35502
+
35503
+ //#endregion
35504
+ //#region src/deployment/nested-output-templates.ts
35505
+ function childTemplateLoader(nestedTemplates) {
35506
+ if (nestedTemplates === void 0) return void 0;
35507
+ const read = /* @__PURE__ */ new Map();
35508
+ const loaderOver = (index) => (logicalId) => {
35509
+ const templatePath = index[logicalId];
35510
+ if (typeof templatePath !== "string") return void 0;
35511
+ const key = path.resolve(templatePath);
35512
+ if (read.has(key)) return read.get(key);
35513
+ let entry;
35514
+ try {
35515
+ const parsed = JSON.parse(fs.readFileSync(templatePath, "utf-8"));
35516
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) entry = {
35517
+ template: parsed,
35518
+ identity: templateIdentity(templatePath),
35519
+ childTemplate: loaderOver(childIndex(parsed, templatePath))
35520
+ };
35521
+ } catch {
35522
+ entry = void 0;
35523
+ }
35524
+ read.set(key, entry);
35525
+ return entry;
35526
+ };
35527
+ return loaderOver(nestedTemplates);
35528
+ }
35529
+ function childIndex(template, templatePath) {
35530
+ const dir = path.dirname(templatePath);
35531
+ const index = Object.create(null);
35532
+ for (const { logicalId, assetPath } of listNestedTemplateRows(template)) {
35533
+ if (isAbsoluteAssetPath(assetPath)) continue;
35534
+ const resolved = resolveAssemblyPath(dir, assetPath);
35535
+ if (resolved.contained) index[logicalId] = resolved.path;
35536
+ }
35537
+ return index;
35538
+ }
35539
+
34017
35540
  //#endregion
34018
35541
  //#region src/deployment/recreate-target-promotion.ts
34019
35542
  function recreateTargetIdsFor(recreateTargets, stackName) {
@@ -34118,6 +35641,17 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
34118
35641
  });
34119
35642
  const parameterValues = await this.resolver.resolveParameters(template, this.options.parameters, { ...this.options.inheritedSecrets && hasMaskableValues(this.options.inheritedSecrets) && { inheritedSecrets: this.options.inheritedSecrets } });
34120
35643
  this.logger.debug(`Resolved ${Object.keys(parameterValues).length} parameters: ${Object.keys(parameterValues).join(", ")}`);
35644
+ const backfillNoEchoValues = noEchoParameterValueSeed(template.Parameters, parameterValues, this.options.inheritedSecrets, this.options.parameters);
35645
+ this.fingerprintNoEchoValues = backfillNoEchoValues;
35646
+ this.fingerprintParameters = parameterInputsFor({
35647
+ template,
35648
+ values: parameterValues,
35649
+ nestedChild: this.options.parentStackInfo !== void 0,
35650
+ supplied: this.options.parameters,
35651
+ passedClasses: this.options.passedParameterClasses
35652
+ });
35653
+ this.fingerprintChildTemplates = childTemplateLoader(getCurrentNestedStackContext()?.nestedTemplates);
35654
+ let maskedFingerprintsBackfilled = backfillMaskedPropertyFingerprints(currentState.resources, template, backfillNoEchoValues) > 0;
34121
35655
  const context = this.buildResolverContext({
34122
35656
  template,
34123
35657
  resources: currentState.resources,
@@ -34139,7 +35673,10 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
34139
35673
  const effectiveTemplate = this.templateParser.filterResourcesByCondition(template, conditions);
34140
35674
  const orphanCountBeforeAdoption = (currentState.orphans ?? []).length;
34141
35675
  const orphanPlan = await this.adoptRollbackOrphans(currentState, effectiveTemplate);
34142
- if (Object.keys(orphanPlan.adopted).length > 0) this.stampReasonlessParameterRefusals(currentState.resources, template);
35676
+ if (Object.keys(orphanPlan.adopted).length > 0) {
35677
+ this.stampReasonlessParameterRefusals(currentState.resources, template);
35678
+ if (backfillMaskedPropertyFingerprints(currentState.resources, template, backfillNoEchoValues) > 0) maskedFingerprintsBackfilled = true;
35679
+ }
34143
35680
  const orphansChanged = Object.keys(orphanPlan.adopted).length > 0 || (currentState.orphans ?? []).length !== orphanCountBeforeAdoption;
34144
35681
  const resourceTypes = new Set(Object.values(effectiveTemplate.Resources || {}).map((r) => r.Type).filter((type) => type !== "AWS::CDK::Metadata"));
34145
35682
  this.providerRegistry.validateResourceTypes(resourceTypes);
@@ -34165,8 +35702,19 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
34165
35702
  diffResolverContext.bestEffort = true;
34166
35703
  diffResolverContext.skipDynamicReferences = true;
34167
35704
  const diffResolveFn = (value) => this.resolver.resolve(value, diffResolverContext);
34168
- 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));
35705
+ const maskedInputSourcesForDiff = this.maskedInputSources(effectiveTemplate, currentState.resources, conditions, stackName);
35706
+ const maskedInputs = maskedInputSourcesForDiff && {
35707
+ sources: maskedInputSourcesForDiff,
35708
+ rebaselined: /* @__PURE__ */ new Map()
35709
+ };
35710
+ 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);
34169
35711
  createOnlyPrefetch.cancel();
35712
+ for (const [logicalId, fingerprints] of maskedInputs?.rebaselined ?? []) {
35713
+ const record = currentState.resources[logicalId];
35714
+ if (record === void 0) continue;
35715
+ currentState.resources[logicalId] = withRebaselinedFingerprints(record, fingerprints);
35716
+ maskedFingerprintsBackfilled = true;
35717
+ }
34170
35718
  const nestedStackTypeChanges = findNestedStackTypeChanges({
34171
35719
  changes,
34172
35720
  stateResources: currentState.resources
@@ -34216,7 +35764,7 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
34216
35764
  const skippedOutputsChanged = !skippedOutputsEqual(currentState.skippedOutputs, this.skippedOutputs);
34217
35765
  const healedAttributesPending = this.hasUnpersistedHeals(currentState.resources);
34218
35766
  const conditionVerdictsChanged = !conditionVerdictRecordsEqual(readRecordedConditionVerdicts(currentState), conditionVerdicts);
34219
- if (observedRefresh || conditionVerdictsChanged || outputsChanged || exportSetChanged || skippedOutputsChanged || orphansChanged || healedAttributesPending) try {
35767
+ if (observedRefresh || maskedFingerprintsBackfilled || conditionVerdictsChanged || outputsChanged || exportSetChanged || skippedOutputsChanged || orphansChanged || healedAttributesPending) try {
34220
35768
  const refreshedState = {
34221
35769
  version: 10,
34222
35770
  region: this.stackRegion,
@@ -34350,6 +35898,54 @@ function buildResolverContext(base, stackName) {
34350
35898
  ...base.redactedAttributeReads && { redactedAttributeReads: base.redactedAttributeReads }
34351
35899
  };
34352
35900
  }
35901
+ function getAttTargetOf(node) {
35902
+ if (node === null || typeof node !== "object" || Array.isArray(node)) return void 0;
35903
+ const getAtt = node["Fn::GetAtt"];
35904
+ if (Array.isArray(getAtt) && typeof getAtt[0] === "string") return getAtt[0];
35905
+ if (typeof getAtt === "string") return getAtt.split(".")[0];
35906
+ }
35907
+ function maskedInputSources(template, resources, conditions, stackName) {
35908
+ const parameters = this.fingerprintParameters;
35909
+ if (parameters === void 0) return void 0;
35910
+ return {
35911
+ template,
35912
+ parameterInput: parameters.parameterInput,
35913
+ conditions,
35914
+ childTemplate: this.fingerprintChildTemplates,
35915
+ resolve: async (node) => {
35916
+ const { attributeHealer: _healer, ...base } = this.buildResolverContext({
35917
+ template,
35918
+ resources,
35919
+ parameters: parameters.bound,
35920
+ ...conditions && { conditions }
35921
+ }, stackName);
35922
+ const context = {
35923
+ ...base,
35924
+ recordedImports: [],
35925
+ recordedOutputReads: [],
35926
+ bestEffort: true,
35927
+ skipDynamicReferences: true,
35928
+ staleAttributeHeal: { phase: "probe" }
35929
+ };
35930
+ const value = await this.resolver.resolve(structuredClone(node), context);
35931
+ const secrets = context.recordedSecretValues;
35932
+ const target = getAttTargetOf(node);
35933
+ const targetSecrets = target === void 0 ? void 0 : this.perResourceSecrets.get(target);
35934
+ if (targetSecrets !== void 0 && hasMaskableValues(targetSecrets)) {
35935
+ const probe = { value };
35936
+ const redacted = redactSecretsForState(probe, targetSecrets);
35937
+ if (JSON.stringify(redacted) !== JSON.stringify(probe)) return {
35938
+ value,
35939
+ keepAsWritten: true
35940
+ };
35941
+ }
35942
+ return {
35943
+ value,
35944
+ ...secrets && { secrets }
35945
+ };
35946
+ }
35947
+ };
35948
+ }
34353
35949
 
34354
35950
  //#endregion
34355
35951
  //#region src/deployment/label-routing.ts
@@ -34573,6 +36169,10 @@ var DeployEngine = class {
34573
36169
  noEchoAttributeResources = /* @__PURE__ */ new Map();
34574
36170
  perResourceTemplateProps = /* @__PURE__ */ new Map();
34575
36171
  perResourceResolvedType = /* @__PURE__ */ new Map();
36172
+ fingerprintNoEchoValues = void 0;
36173
+ fingerprintParameters = void 0;
36174
+ fingerprintChildTemplates = void 0;
36175
+ perResourceInputFingerprints = /* @__PURE__ */ new Map();
34576
36176
  outputSecrets = /* @__PURE__ */ new Map();
34577
36177
  outputsPassSecretMaps = [];
34578
36178
  outputsTemplateSource = Object.create(null);
@@ -34620,6 +36220,10 @@ var DeployEngine = class {
34620
36220
  this.noEchoAttributeResources = /* @__PURE__ */ new Map();
34621
36221
  this.perResourceTemplateProps = /* @__PURE__ */ new Map();
34622
36222
  this.perResourceResolvedType = /* @__PURE__ */ new Map();
36223
+ this.fingerprintNoEchoValues = void 0;
36224
+ this.fingerprintParameters = void 0;
36225
+ this.fingerprintChildTemplates = void 0;
36226
+ this.perResourceInputFingerprints = /* @__PURE__ */ new Map();
34623
36227
  this.attemptedResolvedProps = /* @__PURE__ */ new Map();
34624
36228
  this.liveTaskLabels = /* @__PURE__ */ new Map();
34625
36229
  this.outputSecrets = /* @__PURE__ */ new Map();
@@ -34646,13 +36250,15 @@ var DeployEngine = class {
34646
36250
  for (const [logicalId, record] of Object.entries(state.resources)) {
34647
36251
  const secrets = this.perResourceSecrets.get(logicalId);
34648
36252
  const templateProps = this.perResourceTemplateProps.get(logicalId);
34649
- resources[logicalId] = scrubResourceRecord(this.withHealedAttributes(logicalId, record), secrets ?? /* @__PURE__ */ new Map(), templateProps);
36253
+ const scrubbed = scrubResourceRecord(this.withHealedAttributes(logicalId, record), secrets ?? /* @__PURE__ */ new Map(), templateProps);
36254
+ resources[logicalId] = withMaskedPropertyFingerprints(scrubbed, record.properties, templateProps, secrets, this.fingerprintNoEchoValues, this.perResourceInputFingerprints.get(logicalId));
34650
36255
  }
34651
36256
  const orphans = state.orphans?.map((entry) => {
34652
36257
  const sameResource = this.perResourceResolvedType.get(entry.logicalId) === entry.state.resourceType;
36258
+ const orphanTemplateProps = sameResource ? this.perResourceTemplateProps.get(entry.logicalId) : void 0;
34653
36259
  return {
34654
36260
  ...entry,
34655
- state: scrubResourceRecord(entry.state, (sameResource ? this.perResourceSecrets.get(entry.logicalId) : void 0) ?? /* @__PURE__ */ new Map(), sameResource ? this.perResourceTemplateProps.get(entry.logicalId) : void 0)
36261
+ 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)
34656
36262
  };
34657
36263
  });
34658
36264
  const outputs = this.redactOutputs(state.outputs);
@@ -34768,6 +36374,7 @@ DeployEngine.prototype.recreateDirectionFor = recreateDirectionFor;
34768
36374
  DeployEngine.prototype.peekRoutingForLabel = peekRoutingForLabel;
34769
36375
  DeployEngine.prototype.preparePropertiesForCcApi = preparePropertiesForCcApi;
34770
36376
  DeployEngine.prototype.buildResolverContext = buildResolverContext;
36377
+ DeployEngine.prototype.maskedInputSources = maskedInputSources;
34771
36378
  DeployEngine.prototype.doDeployWithPrefetch = doDeployWithPrefetch;
34772
36379
  DeployEngine.prototype.executeDeployment = executeDeployment;
34773
36380
  DeployEngine.prototype.persistStateAfterOutputFailure = persistStateAfterOutputFailure;
@@ -34825,5 +36432,5 @@ DeployEngine.prototype.replacementNameOrigin = replacementNameOrigin;
34825
36432
  DeployEngine.prototype.orphanedNameCollisionAdvice = orphanedNameCollisionAdvice;
34826
36433
 
34827
36434
  //#endregion
34828
- export { nestedChildStackName as $, importableOutputs as $a, describeTypeWithThrottleRetry as $i, coerceParameterTypedValue as $n, resolveStateBucketWithDefaultAndSource as $o, refuseMalformedOutputs as $r, acquireIdempotencyToken as $t, ECR_AUTO_DELETE_IMAGES_TAG as A, pathCrossesDottedKey as Aa, findReplacedReadersOfRecreateTargets as Ai, reEnableInstanceApiTermination as An, formatDockerLoginError as Ao, malformedLocalResourceEntriesWarning as Ar, DeploymentEventsStore as At, gray as B, WHOLE_DYNAMIC_REFERENCE_PATTERN as Ba, toFiniteNumber as Bi, explicitRoleArnOrThrow as Bn, escapeRegExp$2 as Bo, malformedResourceEntriesWarning as Br, noEchoParameterValueSeed as Bt, deleteBudgetKey as C, markSameGenerationBag as Ca, unreadableResourceEntries as Ci, isWaitAbandonedError as Cn, buildDockerImage as Co, hasReadableResources as Cr, absoluteAssemblyPathEscape as Cs, effectiveDeletionPolicy as Ct, INDEX_SETTLE_POLL_INTERVAL_MS as D, DYNAMIC_REFERENCE_TOKEN_SCAN as Da, withoutSilentDropProperties as Di, isTerminationProtectionPropagationError as Dn, describeDockerFailure as Do, malformedExportNamesWarning as Dr, resolveAssemblyPath as Ds, updatePartialMessage as Dt, DELETE_INDEX_WAIT_PROCEED_NOTE as E, recoverMaskedOutput as Ea, unwrittenCreateOnlyReplacement as Ei, ec2InstanceProtectionSite as En, describeDockerExecFailure as Eo, malformedDriftResourcePropertiesWarning as Er, renderAssemblyPathEscape as Es, unsupportedFinalSnapshotError as Et, markRefusedBeforeApplying as F, recordNoEchoAttributeValues as Fa, renderStatefulReason as Fi, producerRegionsFromState as Fn, redactDockerArgvValues as Fo, malformedOrphansRefusalMessage as Fr, secretBearing as Ft, namesAnyDeclaredParameter as G, rebuildClientForBucketRegion as Ga, configStringRefusal as Gi, callerEnvCredentials as Gn, synthesisStatusMessage as Go, previewableOrphanRecords as Gr, DEFAULT_RESOURCE_TIMEOUT_MS as Gt, red as H, LockManager as Ha, coerceCfnInteger as Hi, sendableAssumeRoleCommand as Hn, AssetManifestLoader as Ho, malformedResourcesWarning as Hr, collectPublishedOutputNames as Ht, formatResourceLine as I, STATE_SOURCED_BASELINE_RULES as Ia, WARM_THROUGHPUT_MEMBERS as Ii, regionLessSecretName as In, redactedDockerCause as Io, malformedOrphansWarning as Ir, secretBearingStateKeyWarning as It, makeSiblingClaimReader as J, exportNamesCarriedFrom as Ja, requireConfigArray as Ji, s3BucketArn as Jn, resolveApp as Jo, refuseMalformedOrphanRecords as Jr, RollbackInlinePolicyWriters as Jt, reachableDivergentParameters as K, acceptedCreateOnlyDropsOf as Ka, readConfigString as Ki, envCredentialsAreAssumedRole as Kn, getDefaultStateBucketName as Ko, refuseDivergentRecordRegionForDestroy as Kr, DEFAULT_RESOURCE_WARN_AFTER_MS as Kt, createReadOnlyAttributeHealerFactory as L, STATE_SOURCED_CROSS_GENERATION_RULES as La, coerceWarmThroughput as Li, applyRoleArnIfSet as Ln, runDockerForeground as Lo, malformedOutputsRefusalMessage as Lr, secretSafeKeyDisplay as Lt, hasCdkAutoDeleteTag as M, carriesSecretMask as Ma, MULTI_REGION_RECREATE_BLOCKED_TYPES as Mi, INTRINSIC_KEYS as Mn, isDockerClientEnvKey as Mo, malformedOrphanRecordsRefusalMessage as Mr, WITHHELD_NAME_DISPLAY as Mt, isTruthyCfnBoolean as N, recordMaskOnlyValue as Na, isStatefulRecreateTargetForReplace as Ni, IntrinsicFunctionResolver as Nn, isMalformedEnvKey as No, malformedOrphanRecordsWarning as Nr, displayTextOrWithheld as Nt, deleteTableWithIndexBusyRetry as O, dynamicReferenceTokens as Oa, NO_CC_HANDLERS_REASON as Oi, observeThenDisableInstanceApiTermination as On, dockerSpawnEnvWithSensitive as Oo, malformedExportSourceWarning as Or, clearBucketRegionCache as Os, updatePartialReason as Ot, getPriorAttempts as P, recordMaskOnlyValuesIn as Pa, isStatefulRecreateTargetSync as Pi, classifyReplaySecretRegion as Pn, partitionSensitiveEnv as Po, malformedOrphanRowsKeptWarning as Pr, exportAliasCollisionScrubWarning as Pt, getNestedRevertRun as Q, importableOutputKeys as Qa, templateResourceTypes as Qi, s3BucketWebsiteUrl as Qn, resolveStateBucketWithDefault as Qo, refuseMalformedOrphansForOrphan as Qr, withCreateTokenLedger as Qt, bold as R, STATE_SOURCED_READBACK_RULES as Ra, isWarmThroughputDecrease as Ri, assertFlagRoleArn as Rn, runDockerStreaming as Ro, malformedOutputsWarning as Rr, exportNameSecretExposure as Rt, compensateRemovedDeletionProtection as S, maskSecretsInText as Sa, unreadableOrphanRecords as Si, withIndeterminateGuard as Sn, buildDenyExternalAccessPolicy as So, hasReadableOutputs as Sr, ownValue as Ss, createPreDeleteFinalSnapshot as St, resolveDynamoDbDeleteBudgetMs as T, scrubResourceRecord as Ta, findSilentDropProperties as Ti, disableInstanceApiTermination as Tn, describeDockerCapturedOutput as To, isReadableResourceEntry as Tr, displayAssemblyPath as Ts, refusesFinalSnapshot as Tt, yellow as U, isLockInfoExpired as Ua, configBooleanRefusal as Ui, AWS_CREDENTIAL_ENV_KEYS as Un, getDockerImageBySourceHash as Uo, malformedScrubResourceEntriesRefusalMessage as Ur, isExportAliasCollision as Ut, green as V, isSingleDynamicReferenceToken as Va, coerceCfnBoolean as Vi, isIamRoleArn as Vn, stripControlChars as Vo, malformedResourcePropertiesWarning as Vr, collectDeclaredOutputNames as Vt, computeParameterTaint as W, S3StateBackend as Wa, configIntegerRefusal as Wi, applyCallerIdentityCredentials as Wn, Synthesizer as Wo, malformedStateRefusalMessage as Wr, bindingSkippedOutputs as Wt, NESTED_PENDING_PARENT_REASON as X, hasReasonlessBaselineRefusal as Xa, requireConfigString as Xi, s3BucketDualStackDomainName as Xn, resolveCaptureObservedState as Xo, refuseMalformedOrphans as Xr, ledgerForStack as Xt, planOrphanAdoption as Y, hasReadableExportSet as Ya, requireConfigObject as Yi, s3BucketDomainName as Yn, resolveAutoAssetStorage as Yo, refuseMalformedOrphanRecordsForDestroy as Yr, earliestDefined as Yt, dropSettledNestedJournals as Z, hasUnverifiableParameterRefusal as Za, prefetchCreateOnlyPropertyPaths as Zi, s3BucketRegionalDomainName as Zn, resolveSkipPrefix as Zo, refuseMalformedOrphansForDestroy as Zr, reserveStackCreateToken as Zt, perType as _, recordLogOnlyValue as _a, repairMalformedOutputsForReadOnly as _i, ccProtectionRegistryTypes as _n, isCrossRegionRedirect as _o, UNREADABLE_ORPHANS_CONTAINER_ROW as _r, processStackMessages as _s, inheritProducerRegions as _t, conditionInputsFrom as a, DagBuilder as aa, refuseMalformedResourceEntriesForImport as ai, tagMapAsList as an, isSensitiveAttributeName as ao, carriesFetchableDynamicReference as ar, CFN_TEMPLATE_URL_LIMIT as as, replayFailedOperations as at, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as b, errorCauseChain as ba, repairMalformedResourcesForReadOnly as bi, deleteIndeterminateGuards as bn, validateAssetBucketName as bo, displayLogicalId as br, hasPlainPrototype$1 as bs, buildFinalSnapshotIdentifier as bt, isSecretBearingReferenceString as c, inheritNestedStackParameterAssociations as ca, refuseMalformedResourcePropertiesForDrift as ci, stringifyIfAssigned as cn, buildAssetRedirectMap as co, AWS_NO_VALUE as cr, uploadCfnTemplate as cs, destroyStackRecordsView as ct, makeCanonicalizePropertiesFn as d, createUnionSecretMasker as da, refuseMalformedResourcesForDeploy as di, ccBrokenReason as dn, rewriteTemplateAssetReferences as do, refStateLookupFromResource as dr, expectedOwnerParam as ds, recordAfterRollbackUpdate as dt, withRetry as ea, refuseMalformedOutputsForDestroy as ei, DBPROXY_TAGS_WHAT as en, isReadableBag as eo, isUnboundTemplateParameter as er, resolveUseCdkBootstrapAssets as es, revertNestedChildFromJournal as et, withResourceDeadline as f, hasMaskableValues as fa, refuseMalformedResourcesForDestroy as fi, wouldReturnToSdkProvider as fn, AssetModeResolver as fo, parseWebACLArn as fr, PARTITION_TABLE as fs, planFailedOps as ft, isProtectionValueActive as g, recordLogOnlyParameterValue as ga, repairMalformedOrphansForReadOnly as gi, slowCcOperationTimeoutMs as gn, getBootstrapMarkerKey as go, STATE_RESOURCES_MALFORMED as gr, StageLoadError as gs, getCurrentProducerRegions as gt, PROTECTION_PROPERTY_BY_TYPE as h, printingCorpusOf as ha, repairMalformedOrphanRecordsForReadOnly as hi, CloudControlProvider as hn, ensureAssetStorage as ho, STATE_REGION_DIVERGED as hr, AssemblyReader as hs, findNestedStackTypeChanges as ht, conditionFingerprint as i, sameLambdaFunctionAddress as ia, refuseMalformedResourceEntriesForDestroy as ii, refuseMalformedDesiredTags as in, AssetPublisher as io, carriesDynamicReference as ir, CFN_TEMPLATE_BODY_LIMIT as is, withNestedStackContext as it, S3_AUTO_DELETE_OBJECTS_TAG as j, identityKeyFor as ja, shownType as ji, DiffCalculator as jn, getDockerCmd as jo, malformedLocalResourcesWarning as jr, extractDeploymentEventError as jt, waitForIndexesSettled as k, isUncertifiedBaselineMaskPosition as ka, hasNoCloudControlHandlers as ki, reDisableInstanceApiTermination as kn, finchSecretArgvRefusal as ko, malformedLocalOutputsWarning as kr, resolveBucketRegion as ks, DeploymentEventsReader as kt, keptWholeReasonText as l, recordNestedStackParameterExpressions as la, refuseMalformedResourcePropertiesForExport as li, CC_BROKEN_REASON as ln, createAssetRedirectResolver as lo, cfnRefValueFromPhysicalId as lr, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as ls, getStackRecords as lt, recordedProtectionNote as m, logOnlyValueCount as ma, refuseMalformedState as mi, getCurrentResourceSecrets as mn, assertAssetBucketRegion as mo, JSON_LISTING_HOLE_VALUE as mr, derivePartitionAndUrlSuffix as ms, resolveReplacementOldType as mt, IMPLICIT_DELETE_DEPENDENCIES as n, canonicalLambdaFunctionName as na, refuseMalformedResourceEntries as ni, planTagDiff as nn, orphansCarriedFrom as no, getAccountInfo as nr, warnDeprecatedNoPrefixCliFlag as ns, withNestedRevertRun as nt, parentSuppliedValues as o, TemplateParser as oa, refuseMalformedResourceEntriesForImportSave as oi, tagPlanWarning as on, stringifyValue as oo, isNamelessDynamicReferenceError as or, MIGRATE_TMP_PREFIX as os, replayRollback as ot, recordedProtectionEvidence as p, literalSplitDelimitersOf as pa, refuseMalformedResourcesForExport as pi, isCustomResourceType as pn, BOOTSTRAP_MARKER_PREFIX as po, withSharedDrainBudget as pr, canonicalizeRegion as ps, planRollback as pt, resourcesNamingDeclaredParameter as q, describeRegionValueKind as qa, replayWarn as qi, isSettledInstanceState as qn, getLegacyStateBucketName as qo, refuseMalformedNestedChildOutputs as qr, maskingRetryLogger as qt, computeImplicitDeleteEdges as r, lambdaFunctionNameForMask as ra, refuseMalformedResourceEntriesForDeploy as ri, readTagList as rn, shouldRetainResource as ro, isImpossibleEmptyStoredAttribute as rr, ssmResolvedValueType as rs, getCurrentNestedStackContext as rt, readRecordedConditionVerdicts as s, liveMatchesUnresolvedTokenFrame as sa, refuseMalformedResourceEntriesForOrphan as si, definedAttributes as sn, WorkGraph as so, keepsSecretReferenceToken as sr, findLargeInlineResources as ss, awaitInFlightSibling as st, DeployEngine as t, markAuxiliaryFailure as ta, refuseMalformedResourceAttributesForOrphan as ti, DBPROXY_TAG_OPTIONS as tn, orphansAfterRollback as to, parameterTypeMayLoseSecretIdentity as tr, stateBucketExistenceConfirmed as ts, revertedNestedRowIds as tt, mergeNoChangeOutputs as u, carryLogOnlyValues as ua, refuseMalformedResourcePropertiesForOrphan as ui, ProviderRegistry as un, loadPublishableAssetManifest as uo, isStalePlaceholderArnAttribute as ur, decodeListingKey as us, withStackRecords as ut, readProtection as v, shareLogOnlyValues as va, repairMalformedResourceEntriesForReadOnly as vi, unchangedBehindSecretReference as vn, parseBootstrapMarker as vo, UNREADABLE_RESOURCES_MAP_ROW as vr, defineOwnKey as vs, ATOMIC_FINAL_SNAPSHOT_TYPES as vt, resolveDynamoDbDeleteBudgetClock as w, redactSecretsForState as wa, findActionableSilentDrops as wi, markWaitAbandoned as wn, resolveDockerContextDirectory as wo, isReadableOrphanRecord as wr, describeFileReadFailure as ws, isFinalSnapshotError as wt, beginDeleteWait as x, maskSecretsInError as xa, unpreviewableOrphanRecords as xi, deleteSkipReason as xn, validateContainerRepoName as xo, hasReadableOrphans as xr, nullPrototypeRecord as xs, ccRoutedFinalSnapshotError as xt, DynamoDBGlobalTableProvider as y, createSecretMasker as ya, repairMalformedResourcePropertiesForReadOnly as yi, UNSPECIFIED_SKIP_REASON as yn, readBootstrapMarkerBody as yo, deployRefusesOrphanRowsReason as yr, hasOwnKey as ys, PRE_DELETE_SNAPSHOT_TYPES as yt, cyan as z, TEMPLATE_SOURCED_RULES as za, toCfnInteger as zi, assertSendableRoleArn as zn, warnFinchArgvExposure as zo, malformedRenderedContainersWarning as zr, isWholeDynamicReferenceValue as zt };
34829
- //# sourceMappingURL=deploy-engine-BTOCDCWf.js.map
36435
+ 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 };
36436
+ //# sourceMappingURL=deploy-engine-CMRU0DTu.js.map