@go-to-k/cdkd 0.297.0 → 0.298.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/{asg-provider-D9Po293s.js → asg-provider-B1xRE8do.js} +4 -4
  2. package/dist/{asg-provider-D9Po293s.js.map → asg-provider-B1xRE8do.js.map} +1 -1
  3. package/dist/{aws-failure-text-BaWeCWRz.js → aws-failure-text-DtvlUugx.js} +2 -2
  4. package/dist/{aws-failure-text-BaWeCWRz.js.map → aws-failure-text-DtvlUugx.js.map} +1 -1
  5. package/dist/cli.js +2 -2
  6. package/dist/{deploy-engine-dvf1UDuo.js → deploy-engine-CJTG3tft.js} +1586 -577
  7. package/dist/deploy-engine-CJTG3tft.js.map +1 -0
  8. package/dist/{iam-policy-targets-Cz2tPxXk.js → iam-policy-targets-CwKiK9nS.js} +2 -2
  9. package/dist/{iam-policy-targets-Cz2tPxXk.js.map → iam-policy-targets-CwKiK9nS.js.map} +1 -1
  10. package/dist/{iam-role-provider--5HuX51Z.js → iam-role-provider-qxfS4sDT.js} +24 -4
  11. package/dist/{iam-role-provider--5HuX51Z.js.map → iam-role-provider-qxfS4sDT.js.map} +1 -1
  12. package/dist/index.d.ts +21 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +4 -4
  15. package/dist/{neptune-provider-xROL9y31.js → neptune-provider-CU_1O2FR.js} +4 -4
  16. package/dist/{neptune-provider-xROL9y31.js.map → neptune-provider-CU_1O2FR.js.map} +1 -1
  17. package/dist/{program-NRnM6vPK.js → program-BivXyHmd.js} +241 -45
  18. package/dist/program-BivXyHmd.js.map +1 -0
  19. package/dist/{provider-classes-uUFRfL9s.js → provider-classes-1EHrZ847.js} +60 -10
  20. package/dist/provider-classes-1EHrZ847.js.map +1 -0
  21. package/dist/{rds-provider-CU0LZr05.js → rds-provider-J40R0ysf.js} +4 -4
  22. package/dist/{rds-provider-CU0LZr05.js.map → rds-provider-J40R0ysf.js.map} +1 -1
  23. package/dist/{version-DE-djeB0.js → version-D96I6uiO.js} +2 -2
  24. package/dist/{version-DE-djeB0.js.map → version-D96I6uiO.js.map} +1 -1
  25. package/package.json +2 -1
  26. package/dist/deploy-engine-dvf1UDuo.js.map +0 -1
  27. package/dist/program-NRnM6vPK.js.map +0 -1
  28. package/dist/provider-classes-uUFRfL9s.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import { r as getAwsClients, s as __exportAll } from "./aws-clients-CnmtbrxD.js";
2
- import { A as UNRENDERABLE, C as looksLikeCdkdGeneratedName, E as withoutGeneratedFallbackName, F as displayStackName, I as isPasteableIdent, M as displayAwsMessage, N as displayIdent, O as SECRET_REF_MAX_CODE_POINTS, P as displaySafe, R as plainIdentOr, S as getCurrentStackName, T as withStackName, V as truncateCodePoints, a as getLogger, b as generateResourceNameWithFallback, d as installLogLineMaskerSource, f as getLiveRenderer, g as applyDefaultNameForFallback, k as STACK_REF_MAX_CODE_POINTS, o as isStdoutReservedForPayload, r as safeStringify$1, t as describeAwsFailure, u as currentLogLineMasker, v as explicitNamePropertyFor, w as withSkipPrefix, x as getCurrentSkipPrefix, y as generateResourceName, z as safeMsg } from "./aws-failure-text-BaWeCWRz.js";
3
- import { $ as protectedReplacementAdvice, $n as isAmbiguousOutcomeError, $t as credentialFingerprint, A as isQuotableImportValue, An as UNSHOWABLE_VALUE, At as isAuxiliaryMarkOf, B as isTerminalDeleteFailure, Bn as withheldTargetClause, Bt as recoveryCommandFlags, Ct as RETRY_AUXILIARY_OWNER, Dt as createdResourceIdentityBeforeFailure, E as assertRegionMatch, Et as createdBeforeFailure, F as resolveExplicitPhysicalId, Fn as physicalIdShownBesideCommand, G as runDeleteAttempt, Gn as isNameCollisionErrorFrom, H as observeThenDisableProtection, Ht as CUSTOM_RESOURCE_RESPONSE_PREFIX, In as plainOrDescribed, J as DELETION_PROTECTION_DOC_POINTER, Jn as isReplayedNameCollisionFrom, Kn as isNameCooldownError, L as ProtectionFlipRegistry, Ln as quotedOrDescribed, Lt as formatLockExpiry, M as quotedRemedyLogicalId, Mt as markCreatedBeforeFailure, N as refusalTypeShown, Nn as isInertUnquoted, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, On as SHELL_ACTIVE, Ot as hasCreatedBeforeFailure, Pn as pasteableCommand, Pt as buildForceUnlockCommand, Q as pasteableAwsCommand, Qn as isAmbiguousCcHandlerErrorCode, Qt as clientDefaultsFor, R as compensateProtectionFlip, Rn as shellBoundedDisplay, Rt as formatLockOperation, Sn as SynthesisError, St as withDerivedNameMasks, T as RESOURCE_NOT_FOUND, Tn as normalizeAwsError, U as protectionFlipKey, Un as isUpdateUnsupportedError, Ut as DEFAULT_STATE_PREFIX, Vt as sanitizeRecoveryValue, Wn as hasReplayMayCollide, Wt as injectiveKey, Xn as markReplayMayCollide, Xt as ambientClientDefaults, Yt as withPasteableAwsProfile, Zn as formatRetryClassificationSignals, Zt as ambientCredentialConfig, _n as ResourceTimeoutError, _t as createMaskedLogSinks, an as DependencyError, ar as isMarkedNonRetryable, at as startInterruptWatch, bt as maskDeep, cn as IntrinsicResolutionRefusalError, cr as markRedactedCause, ct as canonicalizeRoute53QueryName, d as prepareRemovalForUpdate, dn as LockError, en as AccountIdUnavailableError, er as isIamPropagationError, f as removalWarning, fn as MacroExpansionError, ft as logicalIdShown, gn as ProvisioningError, gt as stateOrphanRecordRemedy, ht as segmentAfterAnchor, i as holdsSecretDerivedEntry, in as CrossAccountSecretRefusalError, it as isInterruptedWaitError, j as normalizeAwsTagsToCfn, jn as commandHole, jt as markAuxiliaryFailure, kn as SHELL_ACTIVE_WHY, kt as isAuxiliaryFailure, l as withUnchangedSecretPrincipalLists, lr as wrapMaskedAwsError, m as withoutInjectedRemovals, mt as resourceTypeShown, nn as CdkdError, nr as isTransientServerError, or as isThrottlingError, ot as ElapsedBudgetRegistry, pn as MalformedProducerRecordRefusalError, qn as isRecreateRetryableError, qt as producerRecordKey, rr as retryClassificationText, sn as DynamicReferenceRegionAmbiguousError, sr as markNonRetryable, st as monotonicNowMs, tn as AssetError, tr as isRetryableTransientError, ut as compositeIdSeparatorRefusal, vn as ResourceUpdateNotSupportedError, vt as createMaskedRetryLogger, w as withoutServerErrorRetries, wt as carryCreatedBeforeFailure, xn as StateError, xt as maskerOrIdentity, yt as isSecretDerivedValue, z as deleteWithProtectionCompensation, zn as shellQuote, zt as formatLockOwner } from "./iam-policy-targets-Cz2tPxXk.js";
2
+ import { A as UNRENDERABLE, C as looksLikeCdkdGeneratedName, E as withoutGeneratedFallbackName, F as displayStackName, H as truncateCodePoints, I as isPasteableIdent, M as displayAwsMessage, N as displayIdent, O as SECRET_REF_MAX_CODE_POINTS, P as displaySafe, R as plainIdentOr, S as getCurrentStackName, T as withStackName, V as terminalSafe, a as getLogger, b as generateResourceNameWithFallback, d as installLogLineMaskerSource, f as getLiveRenderer, g as applyDefaultNameForFallback, k as STACK_REF_MAX_CODE_POINTS, o as isStdoutReservedForPayload, r as safeStringify$1, t as describeAwsFailure, u as currentLogLineMasker, v as explicitNamePropertyFor, w as withSkipPrefix, x as getCurrentSkipPrefix, y as generateResourceName, z as safeMsg } from "./aws-failure-text-DtvlUugx.js";
3
+ import { $ as protectedReplacementAdvice, $n as isAmbiguousOutcomeError, $t as credentialFingerprint, A as isQuotableImportValue, An as UNSHOWABLE_VALUE, At as isAuxiliaryMarkOf, B as isTerminalDeleteFailure, Bn as withheldTargetClause, Bt as recoveryCommandFlags, Ct as RETRY_AUXILIARY_OWNER, Dt as createdResourceIdentityBeforeFailure, E as assertRegionMatch, Et as createdBeforeFailure, F as resolveExplicitPhysicalId, Fn as physicalIdShownBesideCommand, G as runDeleteAttempt, Gn as isNameCollisionErrorFrom, H as observeThenDisableProtection, Ht as CUSTOM_RESOURCE_RESPONSE_PREFIX, In as plainOrDescribed, J as DELETION_PROTECTION_DOC_POINTER, Jn as isReplayedNameCollisionFrom, Kn as isNameCooldownError, L as ProtectionFlipRegistry, Ln as quotedOrDescribed, Lt as formatLockExpiry, M as quotedRemedyLogicalId, Mt as markCreatedBeforeFailure, N as refusalTypeShown, Nn as isInertUnquoted, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, On as SHELL_ACTIVE, Ot as hasCreatedBeforeFailure, Pn as pasteableCommand, Pt as buildForceUnlockCommand, Q as pasteableAwsCommand, Qn as isAmbiguousCcHandlerErrorCode, Qt as clientDefaultsFor, R as compensateProtectionFlip, Rn as shellBoundedDisplay, Rt as formatLockOperation, Sn as SynthesisError, St as withDerivedNameMasks, T as RESOURCE_NOT_FOUND, Tn as normalizeAwsError, U as protectionFlipKey, Un as isUpdateUnsupportedError, Ut as DEFAULT_STATE_PREFIX, Vt as sanitizeRecoveryValue, Wn as hasReplayMayCollide, Wt as injectiveKey, Xn as markReplayMayCollide, Xt as ambientClientDefaults, Yt as withPasteableAwsProfile, Zn as formatRetryClassificationSignals, Zt as ambientCredentialConfig, _n as ResourceTimeoutError, _t as createMaskedLogSinks, an as DependencyError, ar as isMarkedNonRetryable, at as startInterruptWatch, bt as maskDeep, cn as IntrinsicResolutionRefusalError, cr as markRedactedCause, ct as canonicalizeRoute53QueryName, d as prepareRemovalForUpdate, dn as LockError, en as AccountIdUnavailableError, er as isIamPropagationError, f as removalWarning, fn as MacroExpansionError, ft as logicalIdShown, gn as ProvisioningError, gt as stateOrphanRecordRemedy, ht as segmentAfterAnchor, i as holdsSecretDerivedEntry, in as CrossAccountSecretRefusalError, it as isInterruptedWaitError, j as normalizeAwsTagsToCfn, jn as commandHole, jt as markAuxiliaryFailure, kn as SHELL_ACTIVE_WHY, kt as isAuxiliaryFailure, l as withUnchangedSecretPrincipalLists, lr as wrapMaskedAwsError, m as withoutInjectedRemovals, mt as resourceTypeShown, nn as CdkdError, nr as isTransientServerError, or as isThrottlingError, ot as ElapsedBudgetRegistry, pn as MalformedProducerRecordRefusalError, qn as isRecreateRetryableError, qt as producerRecordKey, rr as retryClassificationText, sn as DynamicReferenceRegionAmbiguousError, sr as markNonRetryable, st as monotonicNowMs, tn as AssetError, tr as isRetryableTransientError, ut as compositeIdSeparatorRefusal, vn as ResourceUpdateNotSupportedError, vt as createMaskedRetryLogger, w as withoutServerErrorRetries, wt as carryCreatedBeforeFailure, xn as StateError, xt as maskerOrIdentity, yt as isSecretDerivedValue, z as deleteWithProtectionCompensation, zn as shellQuote, zt as formatLockOwner } from "./iam-policy-targets-CwKiK9nS.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-DE-djeB0.js";
5
+ import { t as getCdkdVersion } from "./version-D96I6uiO.js";
6
6
  import { createHash, randomUUID } from "node:crypto";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
8
8
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketLifecycleConfigurationCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -637,6 +637,7 @@ var AssemblyReader = class {
637
637
  if (!resolvedNested.contained) throw new SynthesisError(`Stack ${displayStackName(stackName)} nested-stack ${displayIdent(logicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolvedNested, assemblyDir)}`);
638
638
  nestedTemplates[logicalId] = resolvedNested.path;
639
639
  }
640
+ const lookupRoleArn = props?.lookupRole?.arn;
640
641
  return {
641
642
  stackName,
642
643
  displayName: artifact.displayName ?? stackName,
@@ -649,6 +650,7 @@ var AssemblyReader = class {
649
650
  account: env?.account !== "unknown-account" ? env?.account : void 0,
650
651
  ...props?.terminationProtection !== void 0 && { terminationProtection: props.terminationProtection },
651
652
  ...Object.keys(nestedTemplates).length > 0 && { nestedTemplates },
653
+ ...typeof lookupRoleArn === "string" && { lookupRoleArn },
652
654
  messages: collectStackMessages(assemblyDir, artifact)
653
655
  };
654
656
  }
@@ -8405,6 +8407,23 @@ function deriveReadbackNeedles(bag, source, secrets, rules) {
8405
8407
  };
8406
8408
  }
8407
8409
 
8410
+ //#endregion
8411
+ //#region src/deployment/secret-redaction/physical-name-copies.ts
8412
+ const physicalNameCopiesOf = /* @__PURE__ */ new WeakMap();
8413
+ function recordPhysicalNameCopy(secrets, physicalId) {
8414
+ if (physicalId === "") return;
8415
+ sideSetOf(physicalNameCopiesOf, secrets).add(physicalId);
8416
+ }
8417
+ function physicalNameSpans(names, value) {
8418
+ const spans = [];
8419
+ if (names === void 0) return spans;
8420
+ for (const name of names) for (let at = value.indexOf(name); at !== -1; at = value.indexOf(name, at + 1)) spans.push({
8421
+ start: at,
8422
+ end: at + name.length
8423
+ });
8424
+ return spans;
8425
+ }
8426
+
8408
8427
  //#endregion
8409
8428
  //#region src/deployment/secret-redaction/redact-state.ts
8410
8429
  function redactSecretsForState(bag, secrets, source, rules = TEMPLATE_DERIVED_RULES) {
@@ -8424,17 +8443,22 @@ function redactSecretsForStatePasses(bag, secrets, source, rules) {
8424
8443
  }
8425
8444
  const regex = buildNeedleRegex(substringNeedlesOf(secrets));
8426
8445
  const wholeValueExpr = (s) => s === "" ? void 0 : secrets.get(s);
8446
+ const physicalNames = physicalNameCopiesOf.get(secrets);
8427
8447
  let vouched;
8428
8448
  const vouchedExpressions = () => vouched ??= new Set(secrets.values());
8429
8449
  const scanLeaf = (value, needles) => {
8430
8450
  const spans = isDynamicReferenceString(value) ? resolvableReferenceSpans(value, vouchedExpressions()) : [];
8451
+ const names = physicalNameSpans(physicalNames, value);
8431
8452
  return value.replace(needles, (match, offset) => {
8432
8453
  if (isStrictlyInsideASpan(spans, offset, offset + match.length)) return match;
8454
+ const end = offset + match.length;
8455
+ if (names.some((n) => n.start <= offset && end <= n.end)) return match;
8433
8456
  return secrets.get(match) ?? "***";
8434
8457
  });
8435
8458
  };
8436
8459
  const walk = (value) => {
8437
8460
  if (typeof value === "string") {
8461
+ if (physicalNames?.has(value) === true) return value;
8438
8462
  const whole = wholeValueExpr(value);
8439
8463
  if (whole !== void 0) return whole;
8440
8464
  if (isSingleDynamicReferenceToken(value) && spanNamesResolvableService(value)) return value;
@@ -8467,6 +8491,133 @@ function scrubResourceRecord(record, secrets, sourceProperties, observedRules) {
8467
8491
  if (record.observedProperties) next.observedProperties = redactSecretsForState(record.observedProperties, secrets, sourceProperties ?? next.properties, observedRules ?? (sourceProperties !== void 0 ? TEMPLATE_SOURCED_RULES : secrets.size === 0 && isSameGenerationBag(record.observedProperties) ? STATE_SOURCED_BASELINE_RULES : STATE_SOURCED_READBACK_RULES));
8468
8492
  return next;
8469
8493
  }
8494
+ function withoutPhysicalNameCopies(secrets, run) {
8495
+ const names = physicalNameCopiesOf.get(secrets);
8496
+ if (names === void 0) return run();
8497
+ physicalNameCopiesOf.delete(secrets);
8498
+ try {
8499
+ return run();
8500
+ } finally {
8501
+ physicalNameCopiesOf.set(secrets, names);
8502
+ }
8503
+ }
8504
+ function withPhysicalNameCopies(secrets, ids, run) {
8505
+ const previous = physicalNameCopiesOf.get(secrets);
8506
+ const names = new Set(previous);
8507
+ for (const id of ids) if (id !== "") names.add(id);
8508
+ physicalNameCopiesOf.set(secrets, names);
8509
+ try {
8510
+ return run();
8511
+ } finally {
8512
+ if (previous === void 0) physicalNameCopiesOf.delete(secrets);
8513
+ else physicalNameCopiesOf.set(secrets, previous);
8514
+ }
8515
+ }
8516
+ function repairPhysicalNameCopyLeaves(stored, legacy, current) {
8517
+ if (typeof stored === "string") return typeof legacy === "string" && typeof current === "string" && stored === legacy && current !== legacy ? current : stored;
8518
+ if (Array.isArray(stored)) {
8519
+ if (!Array.isArray(legacy) || !Array.isArray(current)) return stored;
8520
+ if (legacy.length !== stored.length || current.length !== stored.length) return stored;
8521
+ let changed = false;
8522
+ const out = stored.map((item, i) => {
8523
+ const next = repairPhysicalNameCopyLeaves(item, legacy[i], current[i]);
8524
+ if (next !== item) changed = true;
8525
+ return next;
8526
+ });
8527
+ return changed ? out : stored;
8528
+ }
8529
+ if (stored !== null && typeof stored === "object") {
8530
+ if (legacy === null || typeof legacy !== "object" || Array.isArray(legacy)) return stored;
8531
+ if (current === null || typeof current !== "object" || Array.isArray(current)) return stored;
8532
+ const l = legacy;
8533
+ const c = current;
8534
+ let out;
8535
+ for (const [key, value] of Object.entries(stored)) {
8536
+ if (!Object.hasOwn(l, key) || !Object.hasOwn(c, key)) continue;
8537
+ const next = repairPhysicalNameCopyLeaves(value, l[key], c[key]);
8538
+ if (next !== value) {
8539
+ out ??= { ...stored };
8540
+ out[key] = next;
8541
+ }
8542
+ }
8543
+ return out ?? stored;
8544
+ }
8545
+ return stored;
8546
+ }
8547
+ function embeddedPhysicalNameRewrites(secrets, legacySecrets = secrets) {
8548
+ const names = physicalNameCopiesOf.get(secrets);
8549
+ if (names === void 0) return [];
8550
+ const pairs = [];
8551
+ withoutPhysicalNameCopies(legacySecrets, () => {
8552
+ for (const name of names) {
8553
+ const legacy = redactSecretsForState(name, legacySecrets);
8554
+ if (typeof legacy === "string" && legacy !== name && legacy.includes("{{resolve:") && !isSingleDynamicReferenceToken(legacy) && !legacy.includes("***")) pairs.push([legacy, name]);
8555
+ }
8556
+ });
8557
+ return pairs;
8558
+ }
8559
+ function replaceEmbeddedPhysicalNameRewrites(value, pairs) {
8560
+ if (pairs.length === 0) return value;
8561
+ if (typeof value === "string") {
8562
+ let next = value;
8563
+ for (const [legacy, name] of pairs) next = next.split(legacy).join(name);
8564
+ return next;
8565
+ }
8566
+ if (Array.isArray(value)) {
8567
+ let changed = false;
8568
+ const out = value.map((item) => {
8569
+ const next = replaceEmbeddedPhysicalNameRewrites(item, pairs);
8570
+ if (next !== item) changed = true;
8571
+ return next;
8572
+ });
8573
+ return changed ? out : value;
8574
+ }
8575
+ if (value !== null && typeof value === "object") {
8576
+ let out;
8577
+ for (const [key, item] of Object.entries(value)) {
8578
+ const next = replaceEmbeddedPhysicalNameRewrites(item, pairs);
8579
+ if (next !== item) {
8580
+ out ??= { ...value };
8581
+ out[key] = next;
8582
+ }
8583
+ }
8584
+ return out ?? value;
8585
+ }
8586
+ return value;
8587
+ }
8588
+ function repairEmbeddedPhysicalNamesTowards(stored, target, pairs) {
8589
+ if (pairs.length === 0) return stored;
8590
+ if (typeof stored === "string") {
8591
+ if (typeof target !== "string" || stored === target) return stored;
8592
+ const repaired = replaceEmbeddedPhysicalNameRewrites(stored, pairs);
8593
+ return repaired === target ? repaired : stored;
8594
+ }
8595
+ if (Array.isArray(stored)) {
8596
+ if (!Array.isArray(target) || target.length !== stored.length) return stored;
8597
+ let changed = false;
8598
+ const out = stored.map((item, i) => {
8599
+ const next = repairEmbeddedPhysicalNamesTowards(item, target[i], pairs);
8600
+ if (next !== item) changed = true;
8601
+ return next;
8602
+ });
8603
+ return changed ? out : stored;
8604
+ }
8605
+ if (stored !== null && typeof stored === "object") {
8606
+ if (target === null || typeof target !== "object" || Array.isArray(target)) return stored;
8607
+ const t = target;
8608
+ let out;
8609
+ for (const [key, value] of Object.entries(stored)) {
8610
+ if (!Object.hasOwn(t, key)) continue;
8611
+ const next = repairEmbeddedPhysicalNamesTowards(value, t[key], pairs);
8612
+ if (next !== value) {
8613
+ out ??= { ...stored };
8614
+ out[key] = next;
8615
+ }
8616
+ }
8617
+ return out ?? stored;
8618
+ }
8619
+ return stored;
8620
+ }
8470
8621
 
8471
8622
  //#endregion
8472
8623
  //#region src/deployment/secret-redaction/positions.ts
@@ -17450,6 +17601,15 @@ function conditionsAssumedFalse(conditions) {
17450
17601
  return assumedConditionNames.get(conditions) ?? /* @__PURE__ */ new Set();
17451
17602
  }
17452
17603
 
17604
+ //#endregion
17605
+ //#region src/deployment/noecho-declared.ts
17606
+ function isNoEchoDeclared(noEcho) {
17607
+ return noEcho === true || noEcho === "true";
17608
+ }
17609
+ function declaresNoEcho(definition) {
17610
+ return definition !== null && typeof definition === "object" && isNoEchoDeclared(definition.NoEcho);
17611
+ }
17612
+
17453
17613
  //#endregion
17454
17614
  //#region src/deployment/masked-property-fingerprints.ts
17455
17615
  const FINGERPRINT_LAYOUT$1 = 1;
@@ -17526,7 +17686,7 @@ function parameterInputsFor(args) {
17526
17686
  continue;
17527
17687
  }
17528
17688
  const value = values[name];
17529
- let secret = isPlainObject$2(definition) && (definition["NoEcho"] === true || definition["NoEcho"] === "true") || carriesSecretValue(value, []);
17689
+ let secret = isPlainObject$2(definition) && declaresNoEcho(definition) || carriesSecretValue(value, []);
17530
17690
  if (!secret && args.nestedChild === true && args.supplied !== void 0) {
17531
17691
  if (Object.hasOwn(args.supplied, name)) {
17532
17692
  const passed = args.passedClasses?.get(name);
@@ -17951,7 +18111,7 @@ function childParameterInputs(template, passed) {
17951
18111
  const inputs = /* @__PURE__ */ new Map();
17952
18112
  for (const name of Object.keys(declared)) {
17953
18113
  const definition = declared[name];
17954
- if (isPlainObject$2(definition) && (definition["NoEcho"] === true || definition["NoEcho"] === "true")) inputs.set(name, { kind: "secret" });
18114
+ if (isPlainObject$2(definition) && declaresNoEcho(definition)) inputs.set(name, { kind: "secret" });
17955
18115
  else if (passed.has(name)) {
17956
18116
  const passedClass = passed.get(name);
17957
18117
  inputs.set(name, passedClass === "clean" ? {
@@ -18960,7 +19120,7 @@ function inheritedSecretsCarriedBy(value, inherited) {
18960
19120
  return carried;
18961
19121
  }
18962
19122
  function stringifyParameterForLog(paramDef, value) {
18963
- if (paramDef?.NoEcho === true) return "<redacted>";
19123
+ if (declaresNoEcho(paramDef)) return "<redacted>";
18964
19124
  return stringifyValue(value);
18965
19125
  }
18966
19126
  function boundAltered(original, shown, maxCodePoints) {
@@ -19581,7 +19741,7 @@ async function resolveGetAtt(getAtt, context) {
19581
19741
  redacted: isSensitiveAttributeName(attributeName)
19582
19742
  })}`);
19583
19743
  if (reresolvesNestedReference) return await this.reresolveCrossStackValue(flatValue, nestedStackChildRegionFromLocalArn(resource.physicalId), context, `nested stack ${logicalId} ${this.displayLeaf(attributeName, context)}`, crossStackSourceKey({ "Fn::GetAtt": getAtt }));
19584
- return notedFlatValue;
19744
+ return await this.reresolveRecordedReferences(notedFlatValue, logicalId, context, `${logicalId}.${this.displayLeaf(attributeName, context)}`, crossStackSourceKey({ "Fn::GetAtt": getAtt }));
19585
19745
  }
19586
19746
  if (attributeName.includes(".")) {
19587
19747
  const parts = attributeName.split(".");
@@ -19597,7 +19757,7 @@ async function resolveGetAtt(getAtt, context) {
19597
19757
  structured: isStructured(cursor),
19598
19758
  redacted: isSensitiveAttributeName(attributeName)
19599
19759
  })}`);
19600
- return notedCursor;
19760
+ return await this.reresolveRecordedReferences(notedCursor, logicalId, context, `${logicalId}.${this.displayLeaf(attributeName, context)}`, crossStackSourceKey({ "Fn::GetAtt": getAtt }));
19601
19761
  }
19602
19762
  }
19603
19763
  }
@@ -19669,6 +19829,70 @@ function recordSecretNamedRead(logicalId, value, context) {
19669
19829
  break;
19670
19830
  }
19671
19831
  }
19832
+ async function reresolveRecordedReferences(value, logicalId, context, origin, sourceKey) {
19833
+ if (!carriesDynamicReference(value) || carriesSecretMask(value)) return value;
19834
+ if (context.recordedSecretValues === void 0) return value;
19835
+ if (!referencesProvenLocal(value, logicalId, context)) {
19836
+ this.logger.debug(safeMsg`Not re-resolving the reference(s) in ${this.displayMasked(origin, context)}: the template of ${this.displayMasked(logicalId, context)} does not spell them, so the region that resolved them is unknown`);
19837
+ return value;
19838
+ }
19839
+ if (!await this.referencesMatchPhysicalId(value, logicalId, context)) {
19840
+ this.logger.warn(safeMsg`Serving ${this.displayMasked(origin, context)} as recorded, with its {{resolve:...}} reference(s) unresolved: cdkd cannot confirm the secret still holds the value ${this.displayMasked(logicalId, context)} was deployed with, because its physical id does not contain it. Either the secret changed since then (update ${this.displayMasked(logicalId, context)} so cdkd deploys it with the new value), or the value is not part of its name (a custom resource's Data, a name shorter than four characters), and cdkd sends the recorded reference as before.`);
19841
+ return value;
19842
+ }
19843
+ return await this.reresolveCrossStackValue(value, void 0, context, origin, sourceKey);
19844
+ }
19845
+ async function referencesMatchPhysicalId(value, logicalId, context) {
19846
+ const record = Object.hasOwn(context.resources, logicalId) ? context.resources[logicalId] : void 0;
19847
+ const physicalId = typeof record?.physicalId === "string" ? record.physicalId.toLowerCase() : "";
19848
+ for (const leaf of wholeStringLeavesOf(value)) for (const token of dynamicReferenceTokens(leaf)) {
19849
+ const plaintext = await this.resolveDynamicReferences(token, context);
19850
+ if (plaintext.includes("{{resolve:")) continue;
19851
+ if (plaintext.length < 4) return false;
19852
+ if (!physicalId.includes(plaintext.toLowerCase())) return false;
19853
+ }
19854
+ return true;
19855
+ }
19856
+ function readsAnotherStack(node) {
19857
+ if (Object.hasOwn(node, "Fn::ImportValue") || Object.hasOwn(node, "Fn::GetStackOutput")) return true;
19858
+ if (!Object.hasOwn(node, "Fn::GetAtt")) return false;
19859
+ const getAtt = node["Fn::GetAtt"];
19860
+ const attributeName = typeof getAtt === "string" ? splitGetAttStringForm(getAtt)?.attributeName : Array.isArray(getAtt) ? getAtt[1] : void 0;
19861
+ return typeof attributeName !== "string" || attributeName.startsWith("Outputs.");
19862
+ }
19863
+ function takenIfBranch(node, context) {
19864
+ if (Array.isArray(node) || !Object.hasOwn(node, "Fn::If")) return void 0;
19865
+ const args = node["Fn::If"];
19866
+ if (!Array.isArray(args) || args.length !== 3 || typeof args[0] !== "string") return void 0;
19867
+ const conditions = context.conditions;
19868
+ if (conditions === void 0 || !Object.hasOwn(conditions, args[0])) return void 0;
19869
+ const verdict = conditions[args[0]];
19870
+ if (typeof verdict !== "boolean") return void 0;
19871
+ return { branch: verdict ? args[1] : args[2] };
19872
+ }
19873
+ function referencesProvenLocal(value, logicalId, context) {
19874
+ const resources = context.template.Resources ?? {};
19875
+ if (!Object.hasOwn(resources, logicalId)) return false;
19876
+ const literals = [];
19877
+ let crossStack = false;
19878
+ const walk = (node) => {
19879
+ if (typeof node === "string") {
19880
+ if (node.includes("{{resolve:")) literals.push(node);
19881
+ return;
19882
+ }
19883
+ if (node === null || typeof node !== "object") return;
19884
+ if (!Array.isArray(node) && readsAnotherStack(node)) crossStack = true;
19885
+ const taken = takenIfBranch(node, context);
19886
+ if (taken !== void 0) {
19887
+ walk(taken.branch);
19888
+ return;
19889
+ }
19890
+ for (const child of Object.values(node)) walk(child);
19891
+ };
19892
+ walk(resources[logicalId]?.Properties);
19893
+ if (crossStack) return false;
19894
+ return [...wholeStringLeavesOf(value)].every((leaf) => dynamicReferenceTokens(leaf).every((token) => literals.some((l) => l.includes(token))));
19895
+ }
19672
19896
  function rejectPlaceholderArnAttribute(resource, attributeName, value, logicalId, context, healOutcome) {
19673
19897
  if (!isStalePlaceholderArnAttribute(resource.resourceType, attributeName, value)) return;
19674
19898
  throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${this.displayMasked(logicalId, context)}, ${this.displayMasked(attributeName, context)}] for ${resource.resourceType}: the recorded value ${quotedRender(stringifyValue(this.maskValueLeaves(value, context)), "\"")} is a placeholder written by an older cdkd version — its region and account fields are literal wildcards, so it is not a usable ARN. ` + this.staleRecordRemedy(healOutcome, context)));
@@ -20071,6 +20295,345 @@ function getCfnClient(rawRegion) {
20071
20295
  return client;
20072
20296
  }
20073
20297
 
20298
+ //#endregion
20299
+ //#region src/utils/caller-credentials.ts
20300
+ const AWS_CREDENTIAL_ENV_KEYS = [
20301
+ "AWS_ACCESS_KEY_ID",
20302
+ "AWS_SECRET_ACCESS_KEY",
20303
+ "AWS_SESSION_TOKEN"
20304
+ ];
20305
+ function readEnvCredentials(source = process.env) {
20306
+ const accessKeyId = source["AWS_ACCESS_KEY_ID"];
20307
+ const secretAccessKey = source["AWS_SECRET_ACCESS_KEY"];
20308
+ if (!accessKeyId || !secretAccessKey) return void 0;
20309
+ const sessionToken = source["AWS_SESSION_TOKEN"];
20310
+ return {
20311
+ accessKeyId,
20312
+ secretAccessKey,
20313
+ ...sessionToken ? { sessionToken } : {}
20314
+ };
20315
+ }
20316
+ function callerEnvCredentials() {
20317
+ if (getAssumedRoleCredentials() === void 0) return readEnvCredentials();
20318
+ return getPreAssumeEnvCredentials();
20319
+ }
20320
+ function envCredentialsAreAssumedRole() {
20321
+ return getAssumedRoleCredentials() !== void 0;
20322
+ }
20323
+ function applyCallerIdentityCredentials(env) {
20324
+ if (getAssumedRoleCredentials() === void 0) return;
20325
+ const caller = getPreAssumeEnvCredentials();
20326
+ if (!caller) {
20327
+ for (const key of AWS_CREDENTIAL_ENV_KEYS) delete env[key];
20328
+ return;
20329
+ }
20330
+ env["AWS_ACCESS_KEY_ID"] = caller.accessKeyId;
20331
+ env["AWS_SECRET_ACCESS_KEY"] = caller.secretAccessKey;
20332
+ if (caller.sessionToken) env["AWS_SESSION_TOKEN"] = caller.sessionToken;
20333
+ else delete env["AWS_SESSION_TOKEN"];
20334
+ }
20335
+
20336
+ //#endregion
20337
+ //#region src/utils/role-arn.ts
20338
+ const crossAccountCredentialsCache = /* @__PURE__ */ new Map();
20339
+ const CRED_EXPIRY_SAFETY_MS = 6e4;
20340
+ const IAM_ROLE_ARN_RE = /^arn:(aws[a-z0-9-]*):iam::(\d{12}):role\/[\w+=,.@-]+(?:\/[\w+=,.@-]+)*$/;
20341
+ const IAM_ROLE_ARN_MAX_LENGTH = 2048;
20342
+ const IAM_ROLE_ARN_SHAPE_RE = /^arn:[A-Za-z0-9-]+:iam::[0-9]+:role\/[!-~]+$/;
20343
+ function isIamRoleArn(value) {
20344
+ if (typeof value !== "string") return false;
20345
+ if (value.length > 2048) return false;
20346
+ return IAM_ROLE_ARN_SHAPE_RE.test(value);
20347
+ }
20348
+ function refusedRoleArnMessage(value) {
20349
+ return `AssumeRole refused: the role ARN is not a well-formed IAM role ARN (expected arn:<partition>:iam::<account>:role/<name>, at most ${IAM_ROLE_ARN_MAX_LENGTH} characters): ${shownRefusedValue(value)}. Nothing was sent to STS.`;
20350
+ }
20351
+ function shownRefusedValue(value) {
20352
+ if (value === "") return "(empty)";
20353
+ return displayIdent(value, { maxCodePoints: 613 });
20354
+ }
20355
+ function assertSendableRoleArn(roleArn, makeError = (message) => new Error(message)) {
20356
+ if (typeof roleArn !== "string" || !isIamRoleArn(roleArn)) throw makeError(refusedRoleArnMessage(roleArn));
20357
+ }
20358
+ function sendableAssumeRoleCommand(input, makeError) {
20359
+ assertSendableRoleArn(input.RoleArn, makeError);
20360
+ return new AssumeRoleCommand(input);
20361
+ }
20362
+ function explicitRoleArnOrThrow(flag, raw, makeError = (message) => new Error(message)) {
20363
+ const trimmed = raw.trim();
20364
+ if (!isIamRoleArn(trimmed)) throw makeError(`Invalid ${flag} value: ${refusedRoleArnMessage(raw)}`);
20365
+ return trimmed;
20366
+ }
20367
+ function assertFlagRoleArn(flag, value, makeError = (message) => new Error(message)) {
20368
+ assertSendableRoleArn(value, (message) => makeError(`Invalid ${flag} value: ${message}`));
20369
+ }
20370
+ function parseIamRoleArn(roleArn) {
20371
+ if (roleArn.length > 2048) return null;
20372
+ const match = IAM_ROLE_ARN_RE.exec(roleArn);
20373
+ if (!match || !match[1] || !match[2]) return null;
20374
+ return {
20375
+ partition: match[1],
20376
+ accountId: match[2]
20377
+ };
20378
+ }
20379
+ async function assumeRoleForCrossAccountStateRead(roleArn) {
20380
+ const sourceConfig = ambientCredentialConfig();
20381
+ const cacheKey = JSON.stringify([credentialFingerprint(sourceConfig), roleArn]);
20382
+ const cached = crossAccountCredentialsCache.get(cacheKey);
20383
+ if (cached) {
20384
+ const cachedCreds = await cached;
20385
+ if (!cachedCreds.expiration || Date.now() < cachedCreds.expiration.getTime() - CRED_EXPIRY_SAFETY_MS) return cachedCreds;
20386
+ crossAccountCredentialsCache.delete(cacheKey);
20387
+ }
20388
+ const promise = (async () => {
20389
+ const logger = getLogger().child("role-arn");
20390
+ const displayRoleArn = displayIdent(roleArn, { maxCodePoints: 613 });
20391
+ logger.debug(`Assuming role for cross-account state read: ${displayRoleArn}`);
20392
+ assertSendableRoleArn(roleArn);
20393
+ const sts = new STSClient({ ...clientDefaultsFor(sourceConfig) });
20394
+ try {
20395
+ let response;
20396
+ try {
20397
+ response = await sts.send(sendableAssumeRoleCommand({
20398
+ RoleArn: roleArn,
20399
+ RoleSessionName: `cdkd-xacc-${Date.now()}`,
20400
+ DurationSeconds: 3600
20401
+ }));
20402
+ } catch (err) {
20403
+ const message = displayAwsMessage(err instanceof Error ? err.message : String(err));
20404
+ throw new Error(`AssumeRole into ${displayRoleArn} failed: ${message}. If this is a trust-policy issue, the producer's role must allow sts:AssumeRole from the consumer's principal. See https://cdkd.dev/cross-stack-internals/#iam-permissions for the trust-policy setup.`, { cause: err instanceof Error ? err : void 0 });
20405
+ }
20406
+ if (!response.Credentials) throw new Error(`AssumeRole for cross-account Fn::GetStackOutput returned no credentials (RoleArn=${displayRoleArn})`);
20407
+ const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
20408
+ if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing required credentials fields for cross-account state read (RoleArn=${displayRoleArn})`);
20409
+ logger.info(`Assumed role for cross-account state read: ${displayRoleArn} (session expires ${Expiration?.toISOString() ?? "unknown"})`);
20410
+ return {
20411
+ accessKeyId: AccessKeyId,
20412
+ secretAccessKey: SecretAccessKey,
20413
+ sessionToken: SessionToken,
20414
+ ...Expiration && { expiration: Expiration }
20415
+ };
20416
+ } finally {
20417
+ sts.destroy();
20418
+ }
20419
+ })().catch((err) => {
20420
+ if (crossAccountCredentialsCache.get(cacheKey) === promise) crossAccountCredentialsCache.delete(cacheKey);
20421
+ throw err;
20422
+ });
20423
+ crossAccountCredentialsCache.set(cacheKey, promise);
20424
+ return promise;
20425
+ }
20426
+ async function applyRoleArnIfSet(opts) {
20427
+ const roleArn = opts.roleArn !== void 0 ? opts.roleArn : process.env["CDKD_ROLE_ARN"] || void 0;
20428
+ if (roleArn === void 0) return;
20429
+ if (getAssumedRoleCredentials() !== void 0) throw new Error(SECOND_ROLE_PUBLISH_REFUSAL);
20430
+ const logger = getLogger().child("role-arn");
20431
+ const displayRoleArn = displayIdent(roleArn, { maxCodePoints: 613 });
20432
+ logger.debug(`Assuming role ${displayRoleArn}...`);
20433
+ assertSendableRoleArn(roleArn);
20434
+ const sts = new STSClient({
20435
+ ...awsClientDefaults({ ignoreAssumedRole: true }),
20436
+ ...opts.region && { region: opts.region }
20437
+ });
20438
+ try {
20439
+ let response;
20440
+ try {
20441
+ response = await sts.send(sendableAssumeRoleCommand({
20442
+ RoleArn: roleArn,
20443
+ RoleSessionName: `cdkd-${Date.now()}`,
20444
+ DurationSeconds: 3600
20445
+ }));
20446
+ } catch (err) {
20447
+ throw new Error(`AssumeRole for ${displayRoleArn} failed: ${displayAwsMessage(err instanceof Error ? err.message : String(err))}`, { cause: err instanceof Error ? err : void 0 });
20448
+ }
20449
+ if (!response.Credentials) throw new Error(`AssumeRole returned no credentials for role ${displayRoleArn}`);
20450
+ const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
20451
+ if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing credentials fields for role ${displayRoleArn}`);
20452
+ setPreAssumeEnvCredentials(readEnvCredentials());
20453
+ process.env["AWS_ACCESS_KEY_ID"] = AccessKeyId;
20454
+ process.env["AWS_SECRET_ACCESS_KEY"] = SecretAccessKey;
20455
+ process.env["AWS_SESSION_TOKEN"] = SessionToken;
20456
+ setAssumedRoleCredentials({
20457
+ accessKeyId: AccessKeyId,
20458
+ secretAccessKey: SecretAccessKey,
20459
+ sessionToken: SessionToken,
20460
+ ...Expiration && { expiration: Expiration }
20461
+ });
20462
+ logger.info(`Assumed role ${displayRoleArn} (session expires ${Expiration?.toISOString() ?? "unknown"})`);
20463
+ const selectedProfile = process.env["AWS_PROFILE"];
20464
+ if (selectedProfile !== void 0 && selectedProfile !== "") logger.warn("AWS_PROFILE is set and a role has been assumed. The AWS calls cdkd makes to deploy and read state run as the role. The profile still decides the region, it is what your CDK app resolves during synthesis, and — when you passed `--profile` rather than exporting it — it is the identity a `cdkd local` emulated function or task is given. See https://cdkd.dev/cli-reference/#profile-vs-role-arn");
20465
+ } finally {
20466
+ sts.destroy();
20467
+ }
20468
+ }
20469
+
20470
+ //#endregion
20471
+ //#region src/deployment/intrinsic-resolver/cdk-cross-account-ref.ts
20472
+ function producerLookupOver(stacks) {
20473
+ return (stackName, account, region) => stacks.find((s) => s.stackName === stackName && s.account === account && sameRegion(s.region, region));
20474
+ }
20475
+ const ROLE_NAME = "[\\w+=,.@-]{1,64}";
20476
+ const LITERAL_ROLE_ARN_RE = new RegExp(`^arn:aws[a-z0-9-]*:iam::(\\d{12}):role/(${ROLE_NAME})$`);
20477
+ const JOIN_TAIL_RE = new RegExp(`^:iam::(\\d{12}):role/(${ROLE_NAME})$`);
20478
+ function isExactlyKeyed(value, key) {
20479
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
20480
+ const keys = Object.keys(value);
20481
+ return keys.length === 1 && keys[0] === key;
20482
+ }
20483
+ function roleArnShape(raw) {
20484
+ if (typeof raw === "string") {
20485
+ const match = LITERAL_ROLE_ARN_RE.exec(raw);
20486
+ if (!match || !match[1] || !match[2] || !parseIamRoleArn(raw)) return void 0;
20487
+ return {
20488
+ form: "literal",
20489
+ accountId: match[1],
20490
+ roleName: match[2]
20491
+ };
20492
+ }
20493
+ if (!isExactlyKeyed(raw, "Fn::Join")) return void 0;
20494
+ const join = raw["Fn::Join"];
20495
+ if (!Array.isArray(join) || join.length !== 2 || join[0] !== "") return void 0;
20496
+ const parts = join[1];
20497
+ if (!Array.isArray(parts) || parts.length !== 3 || parts[0] !== "arn:") return void 0;
20498
+ const ref = parts[1];
20499
+ if (!isExactlyKeyed(ref, "Ref") || ref["Ref"] !== "AWS::Partition") return void 0;
20500
+ const tail = parts[2];
20501
+ if (typeof tail !== "string") return void 0;
20502
+ const match = JOIN_TAIL_RE.exec(tail);
20503
+ if (!match || !match[1] || !match[2]) return void 0;
20504
+ return {
20505
+ form: "join",
20506
+ accountId: match[1],
20507
+ roleName: match[2]
20508
+ };
20509
+ }
20510
+ function roleArnOf(shape, region) {
20511
+ const { partition } = derivePartitionAndUrlSuffix(region);
20512
+ return `arn:${partition}:iam::${shape.accountId}:role/${shape.roleName}`;
20513
+ }
20514
+ const CFN_EXEC_ROLE_PRINCIPAL_RE = /^arn:(?:\$\{AWS::Partition\}|aws[a-z0-9-]*):iam::\d{12}:role\/[^/]*cfn-exec-role[^/]*$/;
20515
+ function isCfnExecRolePrincipal(principal) {
20516
+ return isExactlyKeyed(principal, "Fn::Sub") && typeof principal["Fn::Sub"] === "string" && CFN_EXEC_ROLE_PRINCIPAL_RE.test(principal["Fn::Sub"]);
20517
+ }
20518
+ function trustsOnlyCfnExecRoles(document) {
20519
+ if (document === null || typeof document !== "object" || Array.isArray(document)) return false;
20520
+ const statements = document["Statement"];
20521
+ if (!Array.isArray(statements) || statements.length === 0) return false;
20522
+ for (const statement of statements) {
20523
+ if (statement === null || typeof statement !== "object" || Array.isArray(statement)) return false;
20524
+ const principal = statement["Principal"];
20525
+ if (!isExactlyKeyed(principal, "AWS")) return false;
20526
+ const aws = principal["AWS"];
20527
+ const list = Array.isArray(aws) ? aws : [aws];
20528
+ if (list.length === 0 || !list.every(isCfnExecRolePrincipal)) return false;
20529
+ }
20530
+ return true;
20531
+ }
20532
+ function isGeneratedReaderRole(template, roleName) {
20533
+ const resources = template.Resources;
20534
+ if (!resources || typeof resources !== "object") return false;
20535
+ for (const resource of Object.values(resources)) {
20536
+ if (resource === null || typeof resource !== "object") continue;
20537
+ const { Type: type, Properties: properties } = resource;
20538
+ if (type !== "AWS::IAM::Role") continue;
20539
+ if (properties === null || typeof properties !== "object") continue;
20540
+ const props = properties;
20541
+ if (props["RoleName"] !== roleName) continue;
20542
+ if (trustsOnlyCfnExecRoles(props["AssumeRolePolicyDocument"])) return true;
20543
+ }
20544
+ return false;
20545
+ }
20546
+ function producerLookupRoleArn(lookupRoleArn, producerRegion, producerAccount) {
20547
+ if (typeof lookupRoleArn !== "string" || lookupRoleArn === "") return void 0;
20548
+ const { partition } = derivePartitionAndUrlSuffix(producerRegion);
20549
+ const arn = lookupRoleArn.split("${AWS::Partition}").join(partition);
20550
+ const parsed = parseIamRoleArn(arn);
20551
+ if (!parsed || parsed.accountId !== producerAccount) return void 0;
20552
+ return arn;
20553
+ }
20554
+ function classifyCdkCrossAccountRef(shape, producerStackName, producerRegion, lookup) {
20555
+ if (lookup === void 0) return { kind: "not-generated" };
20556
+ const producer = lookup(producerStackName, shape.accountId, producerRegion);
20557
+ if (!producer) return shape.form === "join" ? {
20558
+ kind: "producer-absent",
20559
+ shape
20560
+ } : { kind: "not-generated" };
20561
+ if (!isGeneratedReaderRole(producer.template, shape.roleName)) return { kind: "not-generated" };
20562
+ return {
20563
+ kind: "generated",
20564
+ shape,
20565
+ lookupRoleArn: producerLookupRoleArn(producer.lookupRoleArn, producerRegion, shape.accountId)
20566
+ };
20567
+ }
20568
+ function quotedArg(rendered) {
20569
+ return rendered.startsWith("\"") ? rendered : `'${rendered}'`;
20570
+ }
20571
+ function cdkCrossAccountRefRefusal(parts) {
20572
+ const consumerAccount = parts.consumerAccount !== void 0 && /^\d{12}$/.test(parts.consumerAccount) ? parts.consumerAccount : "<consumer-account>";
20573
+ const reason = parts.reason.replace(/[\s.]+$/, "");
20574
+ const trust = `'cdk bootstrap --trust-for-lookup ${consumerAccount}' (or '--trust ${consumerAccount}')`;
20575
+ const remedyOne = parts.noLookupRole ? `(1) synthesize stack ${parts.producer} with a stack synthesizer that names a lookup role (the default DefaultStackSynthesizer), and in account ${parts.producerAccount} run ${trust} so the identity running cdkd can assume it; or ` : `(1) in account ${parts.producerAccount}, run ${trust} so the identity running cdkd can assume the lookup role; or `;
20576
+ return `Fn::GetStackOutput: cannot read output ${parts.output} of stack ${parts.producer} (region ${parts.region}, account ${parts.producerAccount})${parts.consumer ? ` for stack ${parts.consumer}` : ""}. Its RoleArn names ${parts.roleName}, a role the AWS CDK generates for a cross-account reference that trusts only the consumer account's CloudFormation execution role, which cdkd does not use; cdkd reads the producer's cdkd state through the producer account's CDK lookup role instead, but ${reason}. Fix it one of two ways: ` + remedyOne + `(2) write the reference as cdk.Fn.getStackOutput(${quotedArg(parts.producer)}, ${quotedArg(parts.output)}, ${quotedArg(parts.region)}, '<roleArn>') with a role in account ${parts.producerAccount} that trusts the identity running cdkd and allows s3:GetBucketLocation and s3:GetObject on cdkd-state-${parts.producerAccount}. See https://cdkd.dev/cross-stack-references/#reading-from-another-account`;
20577
+ }
20578
+ function producerAbsentReason(producerAccount) {
20579
+ return `this producer stack (account ${producerAccount}) is not in this app's cloud assembly, so cdkd can neither confirm the role is the generated one nor find the lookup role`;
20580
+ }
20581
+ function noLookupRoleReason(producerAccount) {
20582
+ return `the producer stack's artifact names no CDK lookup role in account ${producerAccount} (its stack synthesizer does not use the bootstrap lookup role)`;
20583
+ }
20584
+ function isLookupRoleDenial(error) {
20585
+ let current = error;
20586
+ for (let depth = 0; depth < 6 && current !== null && typeof current === "object"; depth++) {
20587
+ const name = current.name;
20588
+ if (name === "AccessDenied" || name === "AccessDeniedException" || name === "NoSuchEntity" || name === "NoSuchEntityException") return true;
20589
+ if (current.$metadata?.httpStatusCode === 403) return true;
20590
+ current = current.cause;
20591
+ }
20592
+ return false;
20593
+ }
20594
+ function describeInnermostAwsError(error) {
20595
+ let innermost = error;
20596
+ for (let depth = 0; depth < 6; depth++) {
20597
+ const cause = innermost !== null && typeof innermost === "object" ? innermost.cause : void 0;
20598
+ if (cause === null || typeof cause !== "object") break;
20599
+ innermost = cause;
20600
+ }
20601
+ if (!(innermost instanceof Error)) return displayAwsMessage(String(innermost));
20602
+ const code = innermost.Code;
20603
+ const name = typeof code === "string" && code !== "" ? code : innermost.name;
20604
+ const message = displayAwsMessage(innermost.message);
20605
+ return name && name !== "Error" ? `${displayIdent(name)}: ${message}` : message;
20606
+ }
20607
+ function refuseUnreadableCdkCrossAccountRefs(refs, deployed, consumerOf, lookup) {
20608
+ for (const { consumer, args } of refs) {
20609
+ if (!deployed.has(consumer)) continue;
20610
+ const shape = roleArnShape(args["RoleArn"]);
20611
+ if (shape === void 0) continue;
20612
+ const stackName = args["StackName"];
20613
+ const outputName = args["OutputName"];
20614
+ const consumerStack = consumerOf(consumer);
20615
+ const region = args["Region"] ?? consumerStack.region;
20616
+ if (typeof stackName !== "string" || typeof outputName !== "string") continue;
20617
+ if (typeof region !== "string" || region === "") continue;
20618
+ const verdict = classifyCdkCrossAccountRef(shape, stackName, region, lookup);
20619
+ let reason;
20620
+ if (verdict.kind === "producer-absent") reason = producerAbsentReason(shape.accountId);
20621
+ else if (verdict.kind === "generated" && verdict.lookupRoleArn === void 0) reason = noLookupRoleReason(shape.accountId);
20622
+ if (reason === void 0) continue;
20623
+ throw markNonRetryable(new Error(cdkCrossAccountRefRefusal({
20624
+ consumer: displayStackName(consumer),
20625
+ output: displayIdent(outputName),
20626
+ producer: displayStackName(stackName),
20627
+ region: displayIdent(region),
20628
+ producerAccount: shape.accountId,
20629
+ roleName: displayIdent(shape.roleName),
20630
+ consumerAccount: consumerStack.account,
20631
+ reason,
20632
+ noLookupRole: verdict.kind === "generated"
20633
+ })));
20634
+ }
20635
+ }
20636
+
20074
20637
  //#endregion
20075
20638
  //#region src/deployment/intrinsic-resolver/stack-output.ts
20076
20639
  async function resolveGetStackOutput(arg, context) {
@@ -20094,10 +20657,29 @@ async function resolveGetStackOutput(arg, context) {
20094
20657
  loggedRegionText = this.regionLogText(resolvedRegion, context);
20095
20658
  }
20096
20659
  let roleArn;
20660
+ let cdkRef;
20097
20661
  if ("RoleArn" in args && args["RoleArn"] !== void 0 && args["RoleArn"] !== null) {
20098
20662
  const raw = args["RoleArn"];
20099
- if (typeof raw !== "string" || raw === "") throw markNonRetryable(/* @__PURE__ */ new Error(`Fn::GetStackOutput: RoleArn must be a literal string in the template (no Ref / Fn::GetAtt / Fn::Sub allowed for cross-account references). Got ${raw === null ? "null" : Array.isArray(raw) ? "array" : typeof raw}${typeof raw === "object" ? ` (intrinsic shape: ${this.displayMasked(JSON.stringify(raw).slice(0, 80), context)})` : ""}.`));
20100
- roleArn = raw;
20663
+ const refuseNonLiteral = () => markNonRetryable(/* @__PURE__ */ new Error(`Fn::GetStackOutput: RoleArn must be a literal string in the template (no Ref / Fn::GetAtt / Fn::Sub allowed for cross-account references). Got ${raw === null ? "null" : Array.isArray(raw) ? "array" : typeof raw}${typeof raw === "object" ? ` (intrinsic shape: ${this.displayMasked(JSON.stringify(raw).slice(0, 80), context)})` : ""}.`));
20664
+ const shape = roleArnShape(raw);
20665
+ if ((typeof raw !== "string" || raw === "") && shape === void 0) throw refuseNonLiteral();
20666
+ if (shape !== void 0) {
20667
+ const key = JSON.stringify([
20668
+ shape.form,
20669
+ stackName,
20670
+ shape.accountId,
20671
+ canonicalizeRegion(region),
20672
+ shape.roleName
20673
+ ]);
20674
+ let verdict = this.cdkCrossAccountRefVerdicts.get(key);
20675
+ if (verdict === void 0) {
20676
+ verdict = classifyCdkCrossAccountRef(shape, stackName, region, this.producerLookup);
20677
+ this.cdkCrossAccountRefVerdicts.set(key, verdict);
20678
+ }
20679
+ if (verdict.kind === "not-generated" && typeof raw !== "string") throw refuseNonLiteral();
20680
+ if (verdict.kind !== "not-generated") cdkRef = verdict;
20681
+ }
20682
+ roleArn = typeof raw === "string" ? raw : shape && roleArnOf(shape, region);
20101
20683
  }
20102
20684
  if (!roleArn && context.stackName && context.stackName === stackName && sameRegion(region, this.resolverRegion)) throw markNonRetryable(/* @__PURE__ */ new Error(`Fn::GetStackOutput: cannot reference own stack ${this.displayMaskedIdent(stackName, context, STACK_REF_MAX_CODE_POINTS)} in the same region ${this.displayMaskedIdent(loggedRegionText, context)}`));
20103
20685
  const loggedStackName = this.displayMaskedIdent(stackName, context, STACK_REF_MAX_CODE_POINTS);
@@ -20105,11 +20687,35 @@ async function resolveGetStackOutput(arg, context) {
20105
20687
  const loggedRegion = this.displayMasked(loggedRegionText, context);
20106
20688
  const shownRoleArn = roleArn ? displayIdent(roleArn, { maxCodePoints: 613 }) : "";
20107
20689
  this.logger.debug(`Resolving Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${shownRoleArn}` : ""}`);
20690
+ let readRoleArn = roleArn;
20691
+ let refuseCdkRead;
20692
+ if (cdkRef !== void 0) {
20693
+ const ref = cdkRef;
20694
+ const producerAccount = ref.shape.accountId;
20695
+ const refuseCdkRef = (reason, cause, noLookupRole = false) => markNonRetryable(new Error(cdkCrossAccountRefRefusal({
20696
+ consumer: context.stackName ? this.displayMaskedIdent(context.stackName, context, STACK_REF_MAX_CODE_POINTS) : void 0,
20697
+ output: loggedOutputName,
20698
+ producer: loggedStackName,
20699
+ region: displayIdent(loggedRegion),
20700
+ producerAccount,
20701
+ roleName: displayIdent(ref.shape.roleName),
20702
+ consumerAccount: this.consumerAccount,
20703
+ reason,
20704
+ noLookupRole
20705
+ }), cause === void 0 ? void 0 : { cause }));
20706
+ if (ref.kind === "producer-absent") throw refuseCdkRef(producerAbsentReason(producerAccount));
20707
+ if (ref.lookupRoleArn === void 0) throw refuseCdkRef(noLookupRoleReason(producerAccount), void 0, true);
20708
+ readRoleArn = ref.lookupRoleArn;
20709
+ const shownLookupRoleArn = displayIdent(readRoleArn, { maxCodePoints: 613 });
20710
+ refuseCdkRead = (error) => refuseCdkRef(`assuming the lookup role ${shownLookupRoleArn} or reading cdkd-state-${producerAccount} with it was denied: ${describeInnermostAwsError(error)}`, error);
20711
+ this.logger.debug(safeMsg`Fn::GetStackOutput: ${shownRoleArn} is the AWS CDK-generated cross-account reader role; reading through the producer account's lookup role ${shownLookupRoleArn}`);
20712
+ }
20713
+ const shownReadRoleArn = readRoleArn === roleArn ? shownRoleArn : displayIdent(readRoleArn, { maxCodePoints: 613 });
20108
20714
  let stateData;
20109
20715
  try {
20110
- stateData = roleArn ? await this.getCrossAccountStackState(roleArn, stackName, region, context) : await this.getSameAccountStackState(stackName, region, context);
20716
+ stateData = readRoleArn ? await this.getCrossAccountStackState(readRoleArn, stackName, region, context) : await this.getSameAccountStackState(stackName, region, context);
20111
20717
  } catch (error) {
20112
- this.maskStateReadError(error, [[stackName, this.displayMasked(stackName, context)], [region, loggedRegion]], context);
20718
+ this.maskStateReadError(refuseCdkRead && isLookupRoleDenial(error) ? refuseCdkRead(error) : error, [[stackName, this.displayMasked(stackName, context)], [region, loggedRegion]], context);
20113
20719
  }
20114
20720
  if (!stateData) {
20115
20721
  if (!roleArn && this.cfnFallback) {
@@ -20124,7 +20730,7 @@ async function resolveGetStackOutput(arg, context) {
20124
20730
  return value;
20125
20731
  }
20126
20732
  }
20127
- throw new Error(`Fn::GetStackOutput: stack ${loggedStackName} not found in region ${displayIdent(loggedRegion)}${roleArn ? ` (cross-account via ${shownRoleArn})` : ""}. ${!roleArn && this.cfnFallback ? "Searched cdkd state and CloudFormation stacks. Make sure the producer stack has been deployed (via cdkd or CloudFormation)." : `Make sure the producer stack has been deployed via cdkd.`}`);
20733
+ throw new Error(`Fn::GetStackOutput: stack ${loggedStackName} not found in region ${displayIdent(loggedRegion)}${roleArn ? ` (cross-account via ${shownReadRoleArn})` : ""}. ${!roleArn && this.cfnFallback ? "Searched cdkd state and CloudFormation stacks. Make sure the producer stack has been deployed (via cdkd or CloudFormation)." : `Make sure the producer stack has been deployed via cdkd.`}`);
20128
20734
  }
20129
20735
  if (!hasReadableOutputs(stateData.state)) throw markNonRetryable(new MalformedProducerRecordRefusalError(`Fn::GetStackOutput: the state record of producer stack ${loggedStackName} (${displayIdent(loggedRegion)}) has no readable 'outputs' map — the record is malformed or truncated. cdkd refuses to resolve from it rather than reading it as a map: 'Object.hasOwn' answers TRUE for '0' on a string and for an index on a list, so continuing would resolve ONE CHARACTER or element of the record as this reference's value and this deploy would send it to AWS. Inspect the producer's record with 'cdkd state show' --json, repair or remove it, then re-run.`));
20130
20736
  const outputs = stateData.state.outputs ?? {};
@@ -20135,7 +20741,7 @@ async function resolveGetStackOutput(arg, context) {
20135
20741
  const value = outputs[outputName];
20136
20742
  this.logger.info(`Resolved Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${shownRoleArn}` : ""} (${carriesDynamicReference(value) ? "redacted dynamic reference" : "literal value"})`);
20137
20743
  if (!roleArn) this.recordOutputRead(context, stackName, region, outputName);
20138
- if (roleArn && !context.skipDynamicReferences && carriesDynamicReference(value)) throw markNonRetryable(new CrossAccountSecretRefusalError(`Fn::GetStackOutput: output ${loggedOutputName} of stack ${loggedStackName} (${displayIdent(loggedRegion)}) is a redacted dynamic reference, and this is a CROSS-ACCOUNT reference (RoleArn ${shownRoleArn}). cdkd will not resolve a producer account's secret with the consumer's credentials — a same-named secret in the consumer account would answer instead. Export a non-secret value (e.g. the secret's ARN) and resolve it in the consumer stack, or reference the producer stack from within its own account.`));
20744
+ if (roleArn && !context.skipDynamicReferences && carriesDynamicReference(value)) throw markNonRetryable(new CrossAccountSecretRefusalError(`Fn::GetStackOutput: output ${loggedOutputName} of stack ${loggedStackName} (${displayIdent(loggedRegion)}) is a redacted dynamic reference, and this is a CROSS-ACCOUNT reference (RoleArn ${shownRoleArn}${readRoleArn !== roleArn ? `, read through the producer account's CDK lookup role ${shownReadRoleArn}` : ""}). cdkd will not resolve a producer account's secret with the consumer's credentials — a same-named secret in the consumer account would answer instead. Export a non-secret value (e.g. the secret's ARN) and resolve it in the consumer stack, or reference the producer stack from within its own account.`));
20139
20745
  return await this.reresolveCrossStackValue(value, region, context, `Fn::GetStackOutput ${quotedRender(this.displayLeaf(outputName, context), "'")} (producer ${this.displayLeaf(stackName, context)} / ${this.displayLeaf(loggedRegionText, context)})`, sourceKey, {
20140
20746
  stackName,
20141
20747
  region,
@@ -20208,178 +20814,6 @@ function namedRequestMasks(pairs, context) {
20208
20814
  };
20209
20815
  }
20210
20816
 
20211
- //#endregion
20212
- //#region src/utils/caller-credentials.ts
20213
- const AWS_CREDENTIAL_ENV_KEYS = [
20214
- "AWS_ACCESS_KEY_ID",
20215
- "AWS_SECRET_ACCESS_KEY",
20216
- "AWS_SESSION_TOKEN"
20217
- ];
20218
- function readEnvCredentials(source = process.env) {
20219
- const accessKeyId = source["AWS_ACCESS_KEY_ID"];
20220
- const secretAccessKey = source["AWS_SECRET_ACCESS_KEY"];
20221
- if (!accessKeyId || !secretAccessKey) return void 0;
20222
- const sessionToken = source["AWS_SESSION_TOKEN"];
20223
- return {
20224
- accessKeyId,
20225
- secretAccessKey,
20226
- ...sessionToken ? { sessionToken } : {}
20227
- };
20228
- }
20229
- function callerEnvCredentials() {
20230
- if (getAssumedRoleCredentials() === void 0) return readEnvCredentials();
20231
- return getPreAssumeEnvCredentials();
20232
- }
20233
- function envCredentialsAreAssumedRole() {
20234
- return getAssumedRoleCredentials() !== void 0;
20235
- }
20236
- function applyCallerIdentityCredentials(env) {
20237
- if (getAssumedRoleCredentials() === void 0) return;
20238
- const caller = getPreAssumeEnvCredentials();
20239
- if (!caller) {
20240
- for (const key of AWS_CREDENTIAL_ENV_KEYS) delete env[key];
20241
- return;
20242
- }
20243
- env["AWS_ACCESS_KEY_ID"] = caller.accessKeyId;
20244
- env["AWS_SECRET_ACCESS_KEY"] = caller.secretAccessKey;
20245
- if (caller.sessionToken) env["AWS_SESSION_TOKEN"] = caller.sessionToken;
20246
- else delete env["AWS_SESSION_TOKEN"];
20247
- }
20248
-
20249
- //#endregion
20250
- //#region src/utils/role-arn.ts
20251
- const crossAccountCredentialsCache = /* @__PURE__ */ new Map();
20252
- const CRED_EXPIRY_SAFETY_MS = 6e4;
20253
- const IAM_ROLE_ARN_RE = /^arn:(aws[a-z0-9-]*):iam::(\d{12}):role\/[\w+=,.@-]+(?:\/[\w+=,.@-]+)*$/;
20254
- const IAM_ROLE_ARN_MAX_LENGTH = 2048;
20255
- const IAM_ROLE_ARN_SHAPE_RE = /^arn:[A-Za-z0-9-]+:iam::[0-9]+:role\/[!-~]+$/;
20256
- function isIamRoleArn(value) {
20257
- if (typeof value !== "string") return false;
20258
- if (value.length > 2048) return false;
20259
- return IAM_ROLE_ARN_SHAPE_RE.test(value);
20260
- }
20261
- function refusedRoleArnMessage(value) {
20262
- return `AssumeRole refused: the role ARN is not a well-formed IAM role ARN (expected arn:<partition>:iam::<account>:role/<name>, at most ${IAM_ROLE_ARN_MAX_LENGTH} characters): ${shownRefusedValue(value)}. Nothing was sent to STS.`;
20263
- }
20264
- function shownRefusedValue(value) {
20265
- if (value === "") return "(empty)";
20266
- return displayIdent(value, { maxCodePoints: 613 });
20267
- }
20268
- function assertSendableRoleArn(roleArn, makeError = (message) => new Error(message)) {
20269
- if (typeof roleArn !== "string" || !isIamRoleArn(roleArn)) throw makeError(refusedRoleArnMessage(roleArn));
20270
- }
20271
- function sendableAssumeRoleCommand(input, makeError) {
20272
- assertSendableRoleArn(input.RoleArn, makeError);
20273
- return new AssumeRoleCommand(input);
20274
- }
20275
- function explicitRoleArnOrThrow(flag, raw, makeError = (message) => new Error(message)) {
20276
- const trimmed = raw.trim();
20277
- if (!isIamRoleArn(trimmed)) throw makeError(`Invalid ${flag} value: ${refusedRoleArnMessage(raw)}`);
20278
- return trimmed;
20279
- }
20280
- function assertFlagRoleArn(flag, value, makeError = (message) => new Error(message)) {
20281
- assertSendableRoleArn(value, (message) => makeError(`Invalid ${flag} value: ${message}`));
20282
- }
20283
- function parseIamRoleArn(roleArn) {
20284
- if (roleArn.length > 2048) return null;
20285
- const match = IAM_ROLE_ARN_RE.exec(roleArn);
20286
- if (!match || !match[1] || !match[2]) return null;
20287
- return {
20288
- partition: match[1],
20289
- accountId: match[2]
20290
- };
20291
- }
20292
- async function assumeRoleForCrossAccountStateRead(roleArn) {
20293
- const sourceConfig = ambientCredentialConfig();
20294
- const cacheKey = JSON.stringify([credentialFingerprint(sourceConfig), roleArn]);
20295
- const cached = crossAccountCredentialsCache.get(cacheKey);
20296
- if (cached) {
20297
- const cachedCreds = await cached;
20298
- if (!cachedCreds.expiration || Date.now() < cachedCreds.expiration.getTime() - CRED_EXPIRY_SAFETY_MS) return cachedCreds;
20299
- crossAccountCredentialsCache.delete(cacheKey);
20300
- }
20301
- const promise = (async () => {
20302
- const logger = getLogger().child("role-arn");
20303
- const displayRoleArn = displayIdent(roleArn, { maxCodePoints: 613 });
20304
- logger.debug(`Assuming role for cross-account state read: ${displayRoleArn}`);
20305
- assertSendableRoleArn(roleArn);
20306
- const sts = new STSClient({ ...clientDefaultsFor(sourceConfig) });
20307
- try {
20308
- let response;
20309
- try {
20310
- response = await sts.send(sendableAssumeRoleCommand({
20311
- RoleArn: roleArn,
20312
- RoleSessionName: `cdkd-xacc-${Date.now()}`,
20313
- DurationSeconds: 3600
20314
- }));
20315
- } catch (err) {
20316
- const message = displayAwsMessage(err instanceof Error ? err.message : String(err));
20317
- throw new Error(`AssumeRole into ${displayRoleArn} failed: ${message}. If this is a trust-policy issue, the producer's role must allow sts:AssumeRole from the consumer's principal. See https://cdkd.dev/cross-stack-internals/#iam-permissions for the trust-policy setup.`, { cause: err instanceof Error ? err : void 0 });
20318
- }
20319
- if (!response.Credentials) throw new Error(`AssumeRole for cross-account Fn::GetStackOutput returned no credentials (RoleArn=${displayRoleArn})`);
20320
- const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
20321
- if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing required credentials fields for cross-account state read (RoleArn=${displayRoleArn})`);
20322
- logger.info(`Assumed role for cross-account state read: ${displayRoleArn} (session expires ${Expiration?.toISOString() ?? "unknown"})`);
20323
- return {
20324
- accessKeyId: AccessKeyId,
20325
- secretAccessKey: SecretAccessKey,
20326
- sessionToken: SessionToken,
20327
- ...Expiration && { expiration: Expiration }
20328
- };
20329
- } finally {
20330
- sts.destroy();
20331
- }
20332
- })().catch((err) => {
20333
- if (crossAccountCredentialsCache.get(cacheKey) === promise) crossAccountCredentialsCache.delete(cacheKey);
20334
- throw err;
20335
- });
20336
- crossAccountCredentialsCache.set(cacheKey, promise);
20337
- return promise;
20338
- }
20339
- async function applyRoleArnIfSet(opts) {
20340
- const roleArn = opts.roleArn !== void 0 ? opts.roleArn : process.env["CDKD_ROLE_ARN"] || void 0;
20341
- if (roleArn === void 0) return;
20342
- if (getAssumedRoleCredentials() !== void 0) throw new Error(SECOND_ROLE_PUBLISH_REFUSAL);
20343
- const logger = getLogger().child("role-arn");
20344
- const displayRoleArn = displayIdent(roleArn, { maxCodePoints: 613 });
20345
- logger.debug(`Assuming role ${displayRoleArn}...`);
20346
- assertSendableRoleArn(roleArn);
20347
- const sts = new STSClient({
20348
- ...awsClientDefaults({ ignoreAssumedRole: true }),
20349
- ...opts.region && { region: opts.region }
20350
- });
20351
- try {
20352
- let response;
20353
- try {
20354
- response = await sts.send(sendableAssumeRoleCommand({
20355
- RoleArn: roleArn,
20356
- RoleSessionName: `cdkd-${Date.now()}`,
20357
- DurationSeconds: 3600
20358
- }));
20359
- } catch (err) {
20360
- throw new Error(`AssumeRole for ${displayRoleArn} failed: ${displayAwsMessage(err instanceof Error ? err.message : String(err))}`, { cause: err instanceof Error ? err : void 0 });
20361
- }
20362
- if (!response.Credentials) throw new Error(`AssumeRole returned no credentials for role ${displayRoleArn}`);
20363
- const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
20364
- if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing credentials fields for role ${displayRoleArn}`);
20365
- setPreAssumeEnvCredentials(readEnvCredentials());
20366
- process.env["AWS_ACCESS_KEY_ID"] = AccessKeyId;
20367
- process.env["AWS_SECRET_ACCESS_KEY"] = SecretAccessKey;
20368
- process.env["AWS_SESSION_TOKEN"] = SessionToken;
20369
- setAssumedRoleCredentials({
20370
- accessKeyId: AccessKeyId,
20371
- secretAccessKey: SecretAccessKey,
20372
- sessionToken: SessionToken,
20373
- ...Expiration && { expiration: Expiration }
20374
- });
20375
- logger.info(`Assumed role ${displayRoleArn} (session expires ${Expiration?.toISOString() ?? "unknown"})`);
20376
- const selectedProfile = process.env["AWS_PROFILE"];
20377
- if (selectedProfile !== void 0 && selectedProfile !== "") logger.warn("AWS_PROFILE is set and a role has been assumed. The AWS calls cdkd makes to deploy and read state run as the role. The profile still decides the region, it is what your CDK app resolves during synthesis, and — when you passed `--profile` rather than exporting it — it is the identity a `cdkd local` emulated function or task is given. See https://cdkd.dev/cli-reference/#profile-vs-role-arn");
20378
- } finally {
20379
- sts.destroy();
20380
- }
20381
- }
20382
-
20383
20817
  //#endregion
20384
20818
  //#region src/deployment/intrinsic-resolver/stack-state.ts
20385
20819
  async function getSameAccountStackState(stackName, region, context) {
@@ -21857,8 +22291,9 @@ function recordInheritedNoEchoListElements(resolver, inherited, recorded, value,
21857
22291
  }
21858
22292
  function recordNoEchoParameterValue(paramDef, value, context) {
21859
22293
  const bag = context.recordedSecretValues;
21860
- if (paramDef?.NoEcho !== true || bag === void 0) return;
22294
+ if (!declaresNoEcho(paramDef) || bag === void 0) return;
21861
22295
  recordLogOnlyParameterValue(bag, value);
22296
+ if (paramDef?.NoEcho !== true) return;
21862
22297
  recordNoEchoParameterFreshValue(value, bag, this.publicNoEchoTokens(context));
21863
22298
  }
21864
22299
  function refuseCoercedInheritedSecret(name, paramDef, userValue, inherited) {
@@ -21896,6 +22331,7 @@ function lookupResourceRecord(logicalId, via, context) {
21896
22331
  const loggedId = this.displayMasked(logicalId, context);
21897
22332
  throw markNonRetryable(new IntrinsicResolutionRefusalError(`${via} ${loggedId}: ${isObject ? `the state record's physical id is ${physicalId === null ? "null" : typeof physicalId}, not a string` : `the state record is ${Array.isArray(resource) ? "an array" : typeof resource}, not an object`}. cdkd always records an object with a string id, so this record was edited by hand or written by another tool. ${isObject ? `Set the resource's "physicalId" in the stack's state.json back to the id AWS knows the resource by.` : `Restore the resource's record in the stack's state.json, or remove it and re-import the resource.`}`, void 0, "STATE_PHYSICAL_ID_NOT_STRING"));
21898
22333
  }
22334
+ if (context.recordedSecretValues !== void 0) recordPhysicalNameCopy(context.recordedSecretValues, physicalId);
21899
22335
  return resource;
21900
22336
  }
21901
22337
  async function resolveRef(logicalId, context, onParameter) {
@@ -21904,7 +22340,7 @@ async function resolveRef(logicalId, context, onParameter) {
21904
22340
  const refValue = this.resolveRefValue(logicalId, resource, context);
21905
22341
  recordSecretNamedRead(logicalId, refValue, context);
21906
22342
  this.logger.debug(`Resolved Ref to resource: ${this.logRender(logicalId, context)} resolved to ${this.logRender(String(refValue), context)}`);
21907
- return refValue;
22343
+ return await this.reresolveRecordedReferences(refValue, logicalId, context, `Ref ${logicalId}`, void 0);
21908
22344
  }
21909
22345
  if (context.parameters && Object.hasOwn(context.parameters, logicalId)) {
21910
22346
  const value = context.parameters[logicalId];
@@ -21914,7 +22350,7 @@ async function resolveRef(logicalId, context, onParameter) {
21914
22350
  this.recordInheritedParameterSecrets(logicalId, value, context);
21915
22351
  this.logger.debug(`Resolved Ref to parameter: ${this.logRender(logicalId, context)} resolved to ${this.logRender(stringifyParameterForLog(paramDef, this.maskValueLeaves(value, context)), context, {
21916
22352
  structured: isStructured(value),
21917
- redacted: paramDef?.NoEcho === true
22353
+ redacted: declaresNoEcho(paramDef)
21918
22354
  })}`);
21919
22355
  onParameter?.();
21920
22356
  return value;
@@ -21996,6 +22432,9 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
21996
22432
  explicitRegionLogText;
21997
22433
  strictGetAtt;
21998
22434
  cfnFallback;
22435
+ producerLookup;
22436
+ consumerAccount;
22437
+ cdkCrossAccountRefVerdicts = /* @__PURE__ */ new Map();
21999
22438
  cfnClients = /* @__PURE__ */ new Map();
22000
22439
  cfnExportsPromises = /* @__PURE__ */ new Map();
22001
22440
  cfnStackOutputsCache = /* @__PURE__ */ new Map();
@@ -22007,6 +22446,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
22007
22446
  this.explicitRegion = region || void 0;
22008
22447
  this.strictGetAtt = options?.strictGetAtt ?? false;
22009
22448
  this.cfnFallback = options?.cfnFallback ?? true;
22449
+ this.producerLookup = options?.producerLookup;
22450
+ this.consumerAccount = options?.consumerAccount;
22010
22451
  }
22011
22452
  getPhysicalIdFallbackCount() {
22012
22453
  return this.physicalIdFallbackCount;
@@ -22201,6 +22642,8 @@ IntrinsicFunctionResolver.prototype.pushRedactedAttributeRead = pushRedactedAttr
22201
22642
  IntrinsicFunctionResolver.prototype.resolveGetAtt = resolveGetAtt;
22202
22643
  IntrinsicFunctionResolver.prototype.publicNoEchoTokens = publicNoEchoTokens;
22203
22644
  IntrinsicFunctionResolver.prototype.noteAttributeSecrecy = noteAttributeSecrecy;
22645
+ IntrinsicFunctionResolver.prototype.reresolveRecordedReferences = reresolveRecordedReferences;
22646
+ IntrinsicFunctionResolver.prototype.referencesMatchPhysicalId = referencesMatchPhysicalId;
22204
22647
  IntrinsicFunctionResolver.prototype.rejectPlaceholderArnAttribute = rejectPlaceholderArnAttribute;
22205
22648
  IntrinsicFunctionResolver.prototype.staleRecordRemedy = staleRecordRemedy;
22206
22649
  IntrinsicFunctionResolver.prototype.unenrichedRemedy = unenrichedRemedy;
@@ -23028,6 +23471,511 @@ function deleteIndeterminateGuards(result) {
23028
23471
  return out;
23029
23472
  }
23030
23473
 
23474
+ //#endregion
23475
+ //#region src/deployment/inline-policy-claims.ts
23476
+ function isInlinePolicyClaimedByCompletedWriter(args, kind, principal, policyName) {
23477
+ const { selfLogicalId, writers, changes, stateResources } = args;
23478
+ for (const [lid, write] of writers) {
23479
+ if (lid === selfLogicalId || !Object.hasOwn(stateResources, lid)) continue;
23480
+ const record = stateResources[lid];
23481
+ const standalone = standaloneInlinePolicyOf(record.resourceType, record.properties);
23482
+ if (standalone !== void 0) {
23483
+ if (standalone.kind === kind && sameIamName(standalone.principal, principal) && sameIamName(standalone.policyName, policyName)) return true;
23484
+ continue;
23485
+ }
23486
+ if (record.provisionedBy === "cc-api") continue;
23487
+ const props = record.properties ?? {};
23488
+ if (record.resourceType === "AWS::IAM::Policy") {
23489
+ if (!sameIamName(record.physicalId, policyName)) continue;
23490
+ const listed = props[POLICY_LIST_FIELDS[kind]];
23491
+ if (Array.isArray(listed) && listed.some((p) => sameIamName(p, principal))) return true;
23492
+ continue;
23493
+ }
23494
+ if (!Object.hasOwn(PRINCIPAL_KINDS, record.resourceType)) continue;
23495
+ if (PRINCIPAL_KINDS[record.resourceType] !== kind) continue;
23496
+ if (!sameIamName(record.physicalId, principal)) continue;
23497
+ if (write !== "create" && !ownPoliciesChange(changes.get(lid))) continue;
23498
+ const policies = props["Policies"];
23499
+ if (!Array.isArray(policies)) continue;
23500
+ if (policies.some((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && sameIamName(entry["PolicyName"], policyName))) return true;
23501
+ }
23502
+ return false;
23503
+ }
23504
+ var RollbackInlinePolicyWriters = class {
23505
+ entries = /* @__PURE__ */ new Map();
23506
+ removals = /* @__PURE__ */ new Map();
23507
+ unsettled = /* @__PURE__ */ new Map();
23508
+ notePending(ops) {
23509
+ for (const op of ops) if (!this.unsettled.has(op)) this.unsettled.set(op, {
23510
+ logicalId: op.logicalId,
23511
+ state: "pending"
23512
+ });
23513
+ }
23514
+ noteOutcome(op, completed) {
23515
+ if (!completed) {
23516
+ this.unsettled.set(op, {
23517
+ logicalId: op.logicalId,
23518
+ state: "failed"
23519
+ });
23520
+ return;
23521
+ }
23522
+ for (const [key, entry] of this.unsettled) if (key === op || entry.logicalId === op.logicalId) this.unsettled.delete(key);
23523
+ }
23524
+ record(logicalId, write, record, policiesChanged, via) {
23525
+ if (via === "cc-api" && !isStandaloneInlinePolicyType(record.resourceType)) {
23526
+ this.entries.delete(logicalId);
23527
+ return;
23528
+ }
23529
+ this.entries.set(logicalId, {
23530
+ write,
23531
+ record,
23532
+ policiesChanged
23533
+ });
23534
+ }
23535
+ claimedFor(resourceType, logicalId, stateResources) {
23536
+ if (resourceType !== "AWS::IAM::Policy" && !Object.hasOwn(PRINCIPAL_KINDS, resourceType) && !isStandaloneInlinePolicyType(resourceType)) return;
23537
+ return (kind, principal, policyName) => {
23538
+ const writers = /* @__PURE__ */ new Map();
23539
+ const changes = /* @__PURE__ */ new Map();
23540
+ for (const [lid, entry] of this.entries) {
23541
+ if (!Object.hasOwn(stateResources, lid) || stateResources[lid] !== entry.record) continue;
23542
+ writers.set(lid, entry.write);
23543
+ if (entry.policiesChanged) changes.set(lid, {
23544
+ logicalId: lid,
23545
+ changeType: "UPDATE",
23546
+ resourceType: entry.record.resourceType,
23547
+ propertyChanges: [{
23548
+ path: "Policies",
23549
+ oldValue: void 0,
23550
+ newValue: void 0,
23551
+ requiresReplacement: false
23552
+ }]
23553
+ });
23554
+ }
23555
+ const claimed = isInlinePolicyClaimedByCompletedWriter({
23556
+ selfLogicalId: logicalId,
23557
+ writers,
23558
+ changes,
23559
+ stateResources
23560
+ }, kind, principal, policyName);
23561
+ if (!claimed) {
23562
+ const key = removalKey(kind, principal, policyName);
23563
+ const noted = this.removals.get(key) ?? {
23564
+ kind,
23565
+ principal,
23566
+ policyName,
23567
+ removers: /* @__PURE__ */ new Map()
23568
+ };
23569
+ noted.removers.set(logicalId, stateResources[logicalId]);
23570
+ this.removals.set(key, noted);
23571
+ }
23572
+ return claimed;
23573
+ };
23574
+ }
23575
+ takeHeldRemovals(stateResources) {
23576
+ const held = [];
23577
+ for (const [key, { kind, principal, policyName, removers }] of this.removals) {
23578
+ const { holders, unreadable } = inlinePolicyHolders(stateResources, kind, principal, policyName);
23579
+ const others = holders.filter((h) => !removers.has(h.logicalId) || stateResources[h.logicalId] !== removers.get(h.logicalId));
23580
+ if (others.length === 0) continue;
23581
+ this.removals.delete(key);
23582
+ const open = new Set([...this.unsettled.values()].map((u) => u.logicalId));
23583
+ const unsettled = [...new Set(others.map((h) => h.logicalId))].filter((id) => open.has(id));
23584
+ held.push({
23585
+ kind,
23586
+ holders: others,
23587
+ unreadable,
23588
+ unsettled
23589
+ });
23590
+ }
23591
+ return held;
23592
+ }
23593
+ };
23594
+ function inlinePolicyHolders(stateResources, kind, principal, policyName) {
23595
+ const holders = [];
23596
+ const unreadable = [];
23597
+ const unnamed = (v) => typeof v !== "string" || !IAM_NAME.test(v);
23598
+ for (const [logicalId, record] of Object.entries(stateResources)) {
23599
+ if (record === null || typeof record !== "object") continue;
23600
+ const props = record.properties ?? {};
23601
+ const standalone = standaloneInlinePolicyOf(record.resourceType, props);
23602
+ if (standalone !== void 0) {
23603
+ if (standalone.kind !== kind) continue;
23604
+ const principalMatches = sameIamName(standalone.principal, principal);
23605
+ const nameMatches = sameIamName(standalone.policyName, policyName);
23606
+ if (principalMatches && nameMatches) holders.push({
23607
+ logicalId,
23608
+ principal: standalone.principal,
23609
+ policyName: standalone.policyName,
23610
+ document: props["PolicyDocument"]
23611
+ });
23612
+ else if ((principalMatches || unnamed(standalone.principal)) && (nameMatches || unnamed(standalone.policyName))) unreadable.push(logicalId);
23613
+ continue;
23614
+ }
23615
+ if (record.resourceType === "AWS::IAM::Policy") {
23616
+ const nameMatches = sameIamName(record.physicalId, policyName);
23617
+ if (!nameMatches && !unnamed(record.physicalId)) continue;
23618
+ const listed = props[POLICY_LIST_FIELDS[kind]];
23619
+ const entries = Array.isArray(listed) ? listed : [];
23620
+ const named = entries.find((p) => sameIamName(p, principal));
23621
+ if (nameMatches && typeof named === "string") holders.push({
23622
+ logicalId,
23623
+ principal: named,
23624
+ policyName: record.physicalId,
23625
+ document: props["PolicyDocument"]
23626
+ });
23627
+ else if (named !== void 0 || entries.some(unnamed)) unreadable.push(logicalId);
23628
+ continue;
23629
+ }
23630
+ if (!Object.hasOwn(PRINCIPAL_KINDS, record.resourceType)) continue;
23631
+ if (PRINCIPAL_KINDS[record.resourceType] !== kind) continue;
23632
+ const principalMatches = sameIamName(record.physicalId, principal);
23633
+ if (!principalMatches && !unnamed(record.physicalId)) continue;
23634
+ const policies = props["Policies"];
23635
+ if (!Array.isArray(policies)) continue;
23636
+ for (const entry of policies) {
23637
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue;
23638
+ const name = entry["PolicyName"];
23639
+ if (principalMatches && sameIamName(name, policyName)) holders.push({
23640
+ logicalId,
23641
+ principal: record.physicalId,
23642
+ policyName: name,
23643
+ document: entry["PolicyDocument"]
23644
+ });
23645
+ else if (unnamed(name) || sameIamName(name, policyName)) unreadable.push(logicalId);
23646
+ }
23647
+ }
23648
+ return {
23649
+ holders,
23650
+ unreadable: [...new Set(unreadable)]
23651
+ };
23652
+ }
23653
+ function sameIamName(a, b) {
23654
+ return typeof a === "string" && IAM_NAME.test(a) && a.toLowerCase() === b.toLowerCase();
23655
+ }
23656
+ function removalKey(kind, principal, policyName) {
23657
+ return JSON.stringify([
23658
+ kind,
23659
+ principal.toLowerCase(),
23660
+ policyName.toLowerCase()
23661
+ ]);
23662
+ }
23663
+ const IAM_NAME = /^[\w+=,.@-]+$/;
23664
+ const POLICY_LIST_FIELDS = {
23665
+ role: "Roles",
23666
+ group: "Groups",
23667
+ user: "Users"
23668
+ };
23669
+ const PRINCIPAL_KINDS = {
23670
+ "AWS::IAM::Role": "role",
23671
+ "AWS::IAM::Group": "group",
23672
+ "AWS::IAM::User": "user"
23673
+ };
23674
+ const STANDALONE_POLICY_KINDS = {
23675
+ "AWS::IAM::RolePolicy": "role",
23676
+ "AWS::IAM::GroupPolicy": "group",
23677
+ "AWS::IAM::UserPolicy": "user"
23678
+ };
23679
+ function isStandaloneInlinePolicyType(resourceType) {
23680
+ return Object.hasOwn(STANDALONE_POLICY_KINDS, resourceType);
23681
+ }
23682
+ function standaloneInlinePolicyOf(resourceType, properties) {
23683
+ if (!isStandaloneInlinePolicyType(resourceType)) return void 0;
23684
+ const kind = STANDALONE_POLICY_KINDS[resourceType];
23685
+ const props = properties ?? {};
23686
+ return {
23687
+ kind,
23688
+ principal: props[PRINCIPAL_NAME_FIELDS[kind]],
23689
+ policyName: props["PolicyName"]
23690
+ };
23691
+ }
23692
+ function standaloneInlinePolicyHandedOff(resourceType, properties, claimed, physicalId) {
23693
+ if (claimed === void 0) return false;
23694
+ const target = standaloneInlinePolicyOf(resourceType, properties);
23695
+ if (target === void 0) return false;
23696
+ const { kind, principal, policyName } = target;
23697
+ if (typeof principal !== "string" || !IAM_NAME.test(principal)) return false;
23698
+ if (typeof policyName !== "string" || !IAM_NAME.test(policyName)) return false;
23699
+ if (physicalId !== void 0 && physicalId.toLowerCase() !== `${policyName}|${principal}`.toLowerCase()) return false;
23700
+ return claimed(kind, principal, policyName) === true;
23701
+ }
23702
+ function isInlinePolicyPrincipalType(resourceType) {
23703
+ return Object.hasOwn(PRINCIPAL_KINDS, resourceType);
23704
+ }
23705
+ function principalKindOf(resourceType) {
23706
+ return Object.hasOwn(PRINCIPAL_KINDS, resourceType) ? PRINCIPAL_KINDS[resourceType] : void 0;
23707
+ }
23708
+ const ANY = "*";
23709
+ const PRINCIPAL_NAME_FIELDS = {
23710
+ role: "RoleName",
23711
+ group: "GroupName",
23712
+ user: "UserName"
23713
+ };
23714
+ function nameKey(value) {
23715
+ return typeof value === "string" && IAM_NAME.test(value) ? value.toLowerCase() : ANY;
23716
+ }
23717
+ function templatePrincipalKeys(entry, kind, templateResources, stateResources) {
23718
+ if (typeof entry === "string") return [nameKey(entry)];
23719
+ const ref = typeof entry === "object" && entry !== null && !Array.isArray(entry) ? entry["Ref"] : void 0;
23720
+ if (typeof ref !== "string" || !Object.hasOwn(templateResources, ref)) return [ANY];
23721
+ const target = templateResources[ref];
23722
+ if (principalKindOf(target.Type) !== kind) return [ANY];
23723
+ return principalSelfKeys(ref, kind, target, stateResources);
23724
+ }
23725
+ function principalSelfKeys(logicalId, kind, template, stateResources) {
23726
+ const keys = [`ref:${logicalId}`];
23727
+ const declared = template?.Properties?.[PRINCIPAL_NAME_FIELDS[kind]];
23728
+ const declaredKey = nameKey(declared);
23729
+ if (declaredKey !== ANY) keys.push(declaredKey);
23730
+ const record = Object.hasOwn(stateResources, logicalId) ? stateResources[logicalId] : void 0;
23731
+ if (record !== void 0 && principalKindOf(record.resourceType) === kind) {
23732
+ const recordedKey = nameKey(record.physicalId);
23733
+ if (recordedKey !== ANY) keys.push(recordedKey);
23734
+ }
23735
+ return keys;
23736
+ }
23737
+ function policiesNames(policies) {
23738
+ if (policies === void 0 || policies === null) return [];
23739
+ if (!Array.isArray(policies)) return [ANY];
23740
+ return policies.map((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) ? nameKey(entry["PolicyName"]) : ANY);
23741
+ }
23742
+ function standaloneClaimSides(logicalId, change, templateResources, stateResources) {
23743
+ const template = Object.hasOwn(templateResources, logicalId) ? templateResources[logicalId] : void 0;
23744
+ const desired = standaloneInlinePolicyOf(change.resourceType, template?.Properties ?? {});
23745
+ if (desired === void 0) return void 0;
23746
+ const { kind } = desired;
23747
+ const name = nameKey(desired.policyName);
23748
+ const sides = {
23749
+ desired: templatePrincipalKeys(desired.principal, kind, templateResources, stateResources).map((principal) => ({
23750
+ kind,
23751
+ principal,
23752
+ name
23753
+ })),
23754
+ old: []
23755
+ };
23756
+ const record = Object.hasOwn(stateResources, logicalId) ? stateResources[logicalId] : void 0;
23757
+ if (record?.resourceType === change.resourceType) {
23758
+ const old = standaloneInlinePolicyOf(change.resourceType, record.properties);
23759
+ sides.old.push({
23760
+ kind,
23761
+ principal: nameKey(old.principal),
23762
+ name: nameKey(old.policyName)
23763
+ });
23764
+ }
23765
+ return sides;
23766
+ }
23767
+ function inlinePolicyClaimsOf(logicalId, change, templateResources, stateResources) {
23768
+ const template = Object.hasOwn(templateResources, logicalId) ? templateResources[logicalId] : void 0;
23769
+ const record = Object.hasOwn(stateResources, logicalId) ? stateResources[logicalId] : void 0;
23770
+ const recorded = record?.resourceType === change.resourceType ? record : void 0;
23771
+ const claims = [];
23772
+ const cross = (kind, principals, names) => {
23773
+ for (const principal of new Set(principals)) for (const name of new Set(names)) claims.push({
23774
+ kind,
23775
+ principal,
23776
+ name
23777
+ });
23778
+ };
23779
+ const standalone = standaloneClaimSides(logicalId, change, templateResources, stateResources);
23780
+ if (standalone !== void 0) return [...standalone.desired, ...standalone.old];
23781
+ if (change.resourceType === "AWS::IAM::Policy") {
23782
+ const desired = template?.Properties ?? {};
23783
+ const old = recorded?.properties ?? {};
23784
+ const names = [];
23785
+ if (desired["PolicyName"] !== void 0) names.push(nameKey(desired["PolicyName"]));
23786
+ if (old["PolicyName"] !== void 0) names.push(nameKey(old["PolicyName"]));
23787
+ if (recorded !== void 0) names.push(nameKey(typeof recorded.physicalId === "string" ? recorded.physicalId.split(":")[0] : recorded.physicalId));
23788
+ if (names.length === 0) return claims;
23789
+ for (const kind of [
23790
+ "role",
23791
+ "group",
23792
+ "user"
23793
+ ]) {
23794
+ const field = POLICY_LIST_FIELDS[kind];
23795
+ const principals = [];
23796
+ const listed = desired[field];
23797
+ if (Array.isArray(listed)) for (const entry of listed) principals.push(...templatePrincipalKeys(entry, kind, templateResources, stateResources));
23798
+ else if (listed !== void 0) principals.push(ANY);
23799
+ const held = old[field];
23800
+ if (Array.isArray(held)) principals.push(...held.map(nameKey));
23801
+ else if (held !== void 0 && held !== null) principals.push(ANY);
23802
+ cross(kind, principals, names);
23803
+ }
23804
+ return claims;
23805
+ }
23806
+ const kind = principalKindOf(change.resourceType);
23807
+ if (kind === void 0) return claims;
23808
+ if (!(change.changeType === "CREATE" || (change.propertyChanges ?? []).some((c) => c.requiresReplacement) || ownPoliciesChange(change))) return claims;
23809
+ cross(kind, principalSelfKeys(logicalId, kind, template, stateResources), [...policiesNames(template?.Properties?.["Policies"]), ...policiesNames(recorded?.properties?.["Policies"])]);
23810
+ return claims;
23811
+ }
23812
+ function orderInlinePolicyWriters(args) {
23813
+ const { writes, changes, templateResources, stateResources, dependencies, rank } = args;
23814
+ const writers = writes.filter((id) => {
23815
+ const type = changes.get(id)?.resourceType;
23816
+ return type === "AWS::IAM::Policy" || type !== void 0 && (isInlinePolicyPrincipalType(type) || isStandaloneInlinePolicyType(type));
23817
+ });
23818
+ if (writers.length < 2) return [];
23819
+ const exact = /* @__PURE__ */ new Map();
23820
+ const loose = [];
23821
+ const all = [];
23822
+ for (const id of writers) for (const claim of inlinePolicyClaimsOf(id, changes.get(id), templateResources, stateResources)) {
23823
+ all.push({
23824
+ id,
23825
+ claim
23826
+ });
23827
+ if (claim.principal === ANY || claim.name === ANY) {
23828
+ loose.push({
23829
+ id,
23830
+ claim
23831
+ });
23832
+ continue;
23833
+ }
23834
+ const key = JSON.stringify([
23835
+ claim.kind,
23836
+ claim.principal,
23837
+ claim.name
23838
+ ]);
23839
+ const ids = exact.get(key) ?? /* @__PURE__ */ new Set();
23840
+ ids.add(id);
23841
+ exact.set(key, ids);
23842
+ }
23843
+ const principalRows = new Set(writers.filter((id) => isInlinePolicyPrincipalType(changes.get(id).resourceType)));
23844
+ const standaloneRows = new Set(writers.filter((id) => isStandaloneInlinePolicyType(changes.get(id).resourceType)));
23845
+ const sides = new Map([...standaloneRows].map((id) => [id, standaloneClaimSides(id, changes.get(id), templateResources, stateResources)]));
23846
+ const sameClaim = (p, q) => p.kind === q.kind && (p.principal === ANY || q.principal === ANY || p.principal === q.principal) && (p.name === ANY || q.name === ANY || p.name === q.name);
23847
+ const releasesFor = (a, b) => sides.get(a).old.some((o) => sides.get(b).desired.some((d) => sameClaim(o, d)));
23848
+ const pairs = /* @__PURE__ */ new Map();
23849
+ const pair = (a, b) => {
23850
+ if (a === b || principalRows.has(a) && principalRows.has(b)) return;
23851
+ const sa = standaloneRows.has(a);
23852
+ const sb = standaloneRows.has(b);
23853
+ let first;
23854
+ if (sa !== sb) first = sa ? b : a;
23855
+ else if (sa && sb) {
23856
+ const aReleases = releasesFor(a, b);
23857
+ if (aReleases !== releasesFor(b, a)) first = aReleases ? a : b;
23858
+ }
23859
+ first ??= rank(a) < rank(b) || rank(a) === rank(b) && a < b ? a : b;
23860
+ const [x, y] = first === a ? [a, b] : [b, a];
23861
+ pairs.set(JSON.stringify([x, y]), [x, y]);
23862
+ };
23863
+ for (const ids of exact.values()) {
23864
+ const list = [...ids];
23865
+ for (let i = 0; i < list.length; i++) for (let j = i + 1; j < list.length; j++) pair(list[i], list[j]);
23866
+ }
23867
+ const meets = (a, b) => a === ANY || b === ANY || a === b;
23868
+ for (const { id, claim } of loose) for (const other of all) {
23869
+ if (other.claim.kind !== claim.kind) continue;
23870
+ if (meets(claim.principal, other.claim.principal) && meets(claim.name, other.claim.name)) pair(id, other.id);
23871
+ }
23872
+ if (pairs.size === 0) return [];
23873
+ const reaches = (from, to) => {
23874
+ const seen = /* @__PURE__ */ new Set();
23875
+ const stack = [from];
23876
+ while (stack.length > 0) {
23877
+ const id = stack.pop();
23878
+ if (id === to) return true;
23879
+ if (seen.has(id)) continue;
23880
+ seen.add(id);
23881
+ for (const dep of dependencies.get(id) ?? []) stack.push(dep);
23882
+ }
23883
+ return false;
23884
+ };
23885
+ const added = [];
23886
+ for (const [before, after] of pairs.values()) {
23887
+ if (reaches(after, before) || reaches(before, after)) continue;
23888
+ const deps = dependencies.get(after) ?? /* @__PURE__ */ new Set();
23889
+ deps.add(before);
23890
+ dependencies.set(after, deps);
23891
+ added.push({
23892
+ before,
23893
+ after
23894
+ });
23895
+ }
23896
+ return added;
23897
+ }
23898
+ function recordInlinePolicyKeys(record) {
23899
+ if (record === void 0 || record === null || typeof record !== "object") return [];
23900
+ const props = record.properties ?? {};
23901
+ const keys = [];
23902
+ const add = (kind, principal, name) => {
23903
+ keys.push(JSON.stringify([
23904
+ kind,
23905
+ nameKey(principal),
23906
+ nameKey(name)
23907
+ ]));
23908
+ };
23909
+ const standalone = standaloneInlinePolicyOf(record.resourceType, props);
23910
+ if (standalone !== void 0) {
23911
+ add(standalone.kind, standalone.principal, standalone.policyName);
23912
+ return keys;
23913
+ }
23914
+ if (record.resourceType === "AWS::IAM::Policy") {
23915
+ const names = [props["PolicyName"], typeof record.physicalId === "string" ? record.physicalId.split(":")[0] : record.physicalId];
23916
+ for (const kind of [
23917
+ "role",
23918
+ "group",
23919
+ "user"
23920
+ ]) {
23921
+ const listed = props[POLICY_LIST_FIELDS[kind]];
23922
+ if (listed === void 0 || listed === null) continue;
23923
+ const principals = Array.isArray(listed) ? listed : [void 0];
23924
+ for (const p of principals) for (const n of names) add(kind, p, n);
23925
+ }
23926
+ return keys;
23927
+ }
23928
+ const kind = principalKindOf(record.resourceType);
23929
+ if (kind === void 0) return keys;
23930
+ for (const name of policiesNames(props["Policies"])) add(kind, record.physicalId, name);
23931
+ return keys;
23932
+ }
23933
+ function orderInlinePolicyReversals(replay, stateResources) {
23934
+ const current = (op) => Object.hasOwn(stateResources, op.logicalId) ? stateResources[op.logicalId] : void 0;
23935
+ const isStandalone = (op) => [current(op), op.previousState].some((r) => r !== void 0 && r !== null && isStandaloneInlinePolicyType(r.resourceType));
23936
+ if (!replay.some(isStandalone)) return [...replay];
23937
+ const keysOf = /* @__PURE__ */ new Map();
23938
+ for (const op of replay) {
23939
+ const keys = [...recordInlinePolicyKeys(current(op)), ...recordInlinePolicyKeys(op.previousState)];
23940
+ if (keys.length > 0) keysOf.set(op, new Set(keys));
23941
+ }
23942
+ if (keysOf.size < 2) return [...replay];
23943
+ const meets = (a, b) => a === ANY || b === ANY || a === b;
23944
+ const collide = (a, b) => {
23945
+ for (const ka of a) {
23946
+ const [kindA, pA, nA] = JSON.parse(ka);
23947
+ for (const kb of b) {
23948
+ const [kindB, pB, nB] = JSON.parse(kb);
23949
+ if (kindA === kindB && meets(pA, pB) && meets(nA, nB)) return true;
23950
+ }
23951
+ }
23952
+ return false;
23953
+ };
23954
+ const dependsOn = (a, b) => [current(a), a.previousState].some((r) => Array.isArray(r?.dependencies) && r.dependencies.includes(b.logicalId));
23955
+ const order = [...replay];
23956
+ for (const op of [...replay].reverse()) {
23957
+ if (!isStandalone(op)) continue;
23958
+ const mine = keysOf.get(op);
23959
+ if (mine === void 0) continue;
23960
+ const at = order.indexOf(op);
23961
+ let last = -1;
23962
+ for (let j = at + 1; j < order.length; j++) {
23963
+ const other = order[j];
23964
+ const theirs = keysOf.get(other);
23965
+ if (dependsOn(op, other) || dependsOn(other, op)) break;
23966
+ if (theirs === void 0 || isStandalone(other)) continue;
23967
+ if (collide(mine, theirs)) last = j;
23968
+ }
23969
+ if (last < 0) continue;
23970
+ order.splice(at, 1);
23971
+ order.splice(last, 0, op);
23972
+ }
23973
+ return order;
23974
+ }
23975
+ function ownPoliciesChange(change) {
23976
+ return (change?.propertyChanges ?? []).some((c) => c.path === "Policies" && c.inPlacePropagated !== true && c.replacementPropagated !== true);
23977
+ }
23978
+
23031
23979
  //#endregion
23032
23980
  //#region src/provisioning/json-patch-generator.ts
23033
23981
  var JsonPatchGenerator = class {
@@ -23290,9 +24238,24 @@ const WRITABLE_GETATT_ATTRIBUTES = {
23290
24238
  "AWS::StepFunctions::Activity": ["Name"],
23291
24239
  "AWS::Transfer::User": ["ServerId", "UserName"]
23292
24240
  };
24241
+ const SHAPE_MISMATCHED_GETATT_ATTRIBUTES = {
24242
+ "AWS::DocDB::DBCluster": ["Port"],
24243
+ "AWS::Events::EventBus": ["Policy"],
24244
+ "AWS::MediaLive::Input": ["Destinations", "Sources"]
24245
+ };
23293
24246
 
23294
24247
  //#endregion
23295
24248
  //#region src/provisioning/read-only-properties.ts
24249
+ function isDefinitiveRefusal(error) {
24250
+ if (isThrottlingError(error)) return false;
24251
+ let current = error;
24252
+ for (let depth = 0; depth < 5 && current != null; depth++) {
24253
+ const status = current.$metadata?.httpStatusCode;
24254
+ if (status !== void 0) return status >= 400 && status < 500;
24255
+ current = current.cause;
24256
+ }
24257
+ return false;
24258
+ }
23296
24259
  const readOnlyPropertiesCache = /* @__PURE__ */ new Map();
23297
24260
  const attributeNamesCache = /* @__PURE__ */ new Map();
23298
24261
  async function getTopLevelAttributeNames(resourceType) {
@@ -23306,12 +24269,24 @@ async function getTopLevelAttributeNames(resourceType) {
23306
24269
  attributeNamesCache.set(resourceType, names);
23307
24270
  return names;
23308
24271
  }
24272
+ const deployAttributeNamesCache = /* @__PURE__ */ new Map();
24273
+ async function getTopLevelDeployAttributeNames(resourceType) {
24274
+ const certified = await getTopLevelAttributeNames(resourceType);
24275
+ if (certified === void 0) return void 0;
24276
+ const mismatched = Object.hasOwn(SHAPE_MISMATCHED_GETATT_ATTRIBUTES, resourceType) ? SHAPE_MISMATCHED_GETATT_ATTRIBUTES[resourceType] : void 0;
24277
+ if (!mismatched || mismatched.length === 0) return certified;
24278
+ const cached = deployAttributeNamesCache.get(resourceType);
24279
+ if (cached) return cached;
24280
+ const names = /* @__PURE__ */ new Set([...certified, ...mismatched]);
24281
+ deployAttributeNamesCache.set(resourceType, names);
24282
+ return names;
24283
+ }
23309
24284
  function getTopLevelReadOnlyProperties(resourceType) {
23310
24285
  if (hasNoRegistrySchema(resourceType)) return Promise.resolve(void 0);
23311
24286
  const cached = readOnlyPropertiesCache.get(resourceType);
23312
24287
  if (cached) return cached;
23313
24288
  const entry = fetchTopLevelReadOnlyProperties(resourceType).catch((error) => {
23314
- readOnlyPropertiesCache.delete(resourceType);
24289
+ if (!isDefinitiveRefusal(error)) readOnlyPropertiesCache.delete(resourceType);
23315
24290
  const message = describeAwsFailure(error).detail;
23316
24291
  getLogger().child("ReadOnlyProperties").debug(`Failed to resolve read-only properties for ${displaySafe(resourceType, { asciiOnly: true })} via cloudformation:DescribeType (${message}).`);
23317
24292
  });
@@ -23728,10 +24703,11 @@ var CloudControlProvider = class {
23728
24703
  async create(logicalId, resourceType, properties, context) {
23729
24704
  const mask = maskerOrIdentity(context?.maskSecrets);
23730
24705
  const idLog = new IdScrubLog(this.logger, mask, holdsSecretDerivedLeaf(properties, mask));
23731
- return inIdLogScope(idLog, () => this.createInIdLogScope(logicalId, resourceType, properties, idLog));
24706
+ return inIdLogScope(idLog, () => this.createInIdLogScope(logicalId, resourceType, properties, idLog, mask));
23732
24707
  }
23733
- async createInIdLogScope(logicalId, resourceType, properties, idLog) {
24708
+ async createInIdLogScope(logicalId, resourceType, properties, idLog, mask) {
23734
24709
  this.logger.debug(`Creating resource ${logicalId} (${resourceType})`);
24710
+ const attributeNamesLookup = getTopLevelDeployAttributeNames(resourceType);
23735
24711
  try {
23736
24712
  const ccProperties = stringifyJsonProperties(resourceType, stripNullValues(properties));
23737
24713
  const desiredState = JSON.stringify(ccProperties);
@@ -23749,7 +24725,9 @@ var CloudControlProvider = class {
23749
24725
  const result = { physicalId: progressEvent.Identifier };
23750
24726
  if (progressEvent.ResourceModel) result.attributes = this.parseResourceModel(progressEvent.ResourceModel);
23751
24727
  result.attributes = await this.mergeSparseModelReadback(resourceType, progressEvent.Identifier, result.attributes || {});
24728
+ const modelKeys = Object.keys(result.attributes);
23752
24729
  result.attributes = await this.enrichResourceAttributes(resourceType, progressEvent.Identifier, result.attributes);
24730
+ result.attributes = await this.maskDeployedNonAttributeKeys(result.attributes, modelKeys, resourceType, progressEvent.Identifier, attributeNamesLookup, properties, mask);
23753
24731
  return result;
23754
24732
  } catch (error) {
23755
24733
  idLog.addId(identifierCarriedBy(error));
@@ -23820,6 +24798,7 @@ var CloudControlProvider = class {
23820
24798
  sentNothing: true
23821
24799
  };
23822
24800
  }
24801
+ const attributeNamesLookup = getTopLevelDeployAttributeNames(resourceType);
23823
24802
  const writeOnlyProperties = await getTopLevelWriteOnlyProperties(resourceType);
23824
24803
  if (writeOnlyProperties.size > 0) {
23825
24804
  const keptOnPreviousSide = getTopLevelKeysHoldingUnreadableCreateOnly(resourceType, cleanProperties);
@@ -23860,7 +24839,9 @@ var CloudControlProvider = class {
23860
24839
  };
23861
24840
  if (progressEvent.ResourceModel) result.attributes = this.parseResourceModel(progressEvent.ResourceModel, idLog);
23862
24841
  result.attributes = await this.mergeSparseModelReadback(resourceType, physicalId, result.attributes || {}, idLog);
24842
+ const modelKeys = Object.keys(result.attributes);
23863
24843
  result.attributes = await this.enrichResourceAttributes(resourceType, physicalId, result.attributes, idLog);
24844
+ result.attributes = await this.maskDeployedNonAttributeKeys(result.attributes, modelKeys, resourceType, physicalId, attributeNamesLookup, properties, maskerOrIdentity(context?.maskSecrets), idLog);
23864
24845
  return result;
23865
24846
  } catch (error) {
23866
24847
  this.handleError(error, "UPDATE", resourceType, logicalId, physicalId);
@@ -23885,10 +24866,14 @@ var CloudControlProvider = class {
23885
24866
  this.logger.debug(`Deleting resource ${logicalId} (${resourceType}), physical ID: ${physicalId}`);
23886
24867
  if (context?.finalSnapshotIdentifier !== void 0) throw new ProvisioningError(`${logicalId} (${resourceType}) requires a final snapshot (DeletionPolicy: Snapshot), but the Cloud Control API delete route has no final-snapshot parameter. Re-run with --skip-final-snapshot after snapshotting manually, or retain the resource.`, resourceType, logicalId, physicalId);
23887
24868
  await this.assertRecordedRegionAgainstClient("pre-delete", context?.expectedRegion, resourceType, logicalId, physicalId);
24869
+ if (standaloneInlinePolicyHandedOff(resourceType, properties, context?.inlinePolicyClaimed, physicalId)) {
24870
+ this.logger.info(` ${logicalId}: not deleting its inline policy, which another resource of this deploy now holds under the same name`);
24871
+ return;
24872
+ }
23888
24873
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
23889
24874
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
23890
24875
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
23891
- const { ASGProvider } = await import("./asg-provider-D9Po293s.js");
24876
+ const { ASGProvider } = await import("./asg-provider-B1xRE8do.js");
23892
24877
  const delegateRegion = ambientRegion();
23893
24878
  let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
23894
24879
  if (asgProvider === void 0) {
@@ -23994,7 +24979,7 @@ var CloudControlProvider = class {
23994
24979
  const family = SDK_DELETE_FAMILIES.get(resourceType);
23995
24980
  const cached = this.sdkDeleteDelegates.get(family);
23996
24981
  if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
23997
- const provider = family === "rds" ? new (await (import("./rds-provider-CU0LZr05.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-xROL9y31.js"))).NeptuneProvider({ region: ccRegion });
24982
+ const provider = family === "rds" ? new (await (import("./rds-provider-J40R0ysf.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-CU_1O2FR.js"))).NeptuneProvider({ region: ccRegion });
23998
24983
  this.sdkDeleteDelegates.set(family, {
23999
24984
  region: ccRegion,
24000
24985
  provider
@@ -24639,6 +25624,25 @@ var CloudControlProvider = class {
24639
25624
  throw error;
24640
25625
  }
24641
25626
  }
25627
+ async maskDeployedNonAttributeKeys(attributes, modelKeys, resourceType, physicalId, attributeNamesLookup, desired, mask, log = this.logger) {
25628
+ const safeType = displaySafe(resourceType, { asciiOnly: true });
25629
+ const attributeNames = await attributeNamesLookup;
25630
+ if (attributeNames === void 0) {
25631
+ log.debug(`Could not resolve the CloudFormation schema for ${safeType}; recording its Cloud Control model unnarrowed for ${displaySafe(physicalId, { asciiOnly: true })}.`);
25632
+ return attributes;
25633
+ }
25634
+ const narrowed = new Set(modelKeys.filter((key) => !attributeNames.has(key) && !isLiteralDeployOnlyKey(resourceType, key, desired, mask)));
25635
+ if (narrowed.size === 0) return attributes;
25636
+ const out = Object.create(null);
25637
+ for (const [key, value] of Object.entries(attributes)) Object.defineProperty(out, key, {
25638
+ value: narrowed.has(key) ? maskLeavesDeep(value) : value,
25639
+ enumerable: true,
25640
+ writable: true,
25641
+ configurable: true
25642
+ });
25643
+ log.debug(`Masked ${narrowed.size} non-attribute key(s) of the ${safeType} Cloud Control model for ${displaySafe(physicalId, { asciiOnly: true })}: they are not Fn::GetAtt attributes of the type.`);
25644
+ return out;
25645
+ }
24642
25646
  async import(input) {
24643
25647
  if (!input.knownPhysicalId) return null;
24644
25648
  const identifier = toCloudControlIdentifier({
@@ -24794,6 +25798,11 @@ function holdsSecretDerivedLeaf(value, mask, depth = 0) {
24794
25798
  return Object.entries(value).some(([key, entry]) => isSecretDerivedValue(key, mask) || holdsSecretDerivedLeaf(entry, mask, depth + 1));
24795
25799
  }
24796
25800
  const IMPORT_YIELDED_NO_ATTRIBUTES_CONSEQUENCE = "Attributes the stack's state already records for this physical id are kept; without them, an Fn::GetAtt against this resource falls back to a value constructed from its physical id.";
25801
+ function isLiteralDeployOnlyKey(resourceType, key, desired, mask) {
25802
+ if (resourceType !== "AWS::SSM::Parameter" || key !== "Value") return false;
25803
+ const declared = desired["Value"];
25804
+ return typeof declared === "string" && !isSecretDerivedValue(declared, mask);
25805
+ }
24797
25806
  function maskLeavesDeep(value) {
24798
25807
  if (Array.isArray(value)) return value.map((element) => maskLeavesDeep(element));
24799
25808
  if (value !== null && typeof value === "object") {
@@ -25152,6 +26161,7 @@ var TemplateNoEchoReresolver = class TemplateNoEchoReresolver {
25152
26161
  logger = getLogger().child("NoEchoDeleteReresolution");
25153
26162
  resolver;
25154
26163
  parametersPromise;
26164
+ printingNoEchoPromise;
25155
26165
  noEchoParameters;
25156
26166
  options;
25157
26167
  constructor(options) {
@@ -25161,7 +26171,7 @@ var TemplateNoEchoReresolver = class TemplateNoEchoReresolver {
25161
26171
  const section = options.template.Parameters;
25162
26172
  if (section !== null && typeof section === "object") for (const [name, definition] of Object.entries(section)) {
25163
26173
  const noEcho = definition?.NoEcho;
25164
- if (noEcho === true || noEcho === "true") declared.add(name);
26174
+ if (isNoEchoDeclared(noEcho)) declared.add(name);
25165
26175
  }
25166
26176
  for (const name of options.inheritedNoEchoParameters ?? []) declared.add(name);
25167
26177
  this.noEchoParameters = declared;
@@ -25213,6 +26223,33 @@ var TemplateNoEchoReresolver = class TemplateNoEchoReresolver {
25213
26223
  for (const name of this.noEchoParameters) if (parameters !== void 0 && Object.hasOwn(parameters, name)) recordLogOnlyParameterValue(bag, parameters[name]);
25214
26224
  return bag;
25215
26225
  }
26226
+ printingNoEchoValues() {
26227
+ this.printingNoEchoPromise ??= this.printingNeedles().then((bag) => hasMaskableValues(bag) ? bag : void 0);
26228
+ return this.printingNoEchoPromise;
26229
+ }
26230
+ async printingNeedles() {
26231
+ const bag = this.newBag();
26232
+ if (this.options.printingSeed !== void 0) carryLogOnlyValues(this.options.printingSeed, bag);
26233
+ if (this.noEchoParameters.size === 0) return bag;
26234
+ const parameters = await this.boundParameters();
26235
+ const section = this.options.template.Parameters ?? {};
26236
+ const supplied = this.options.parameters;
26237
+ for (const name of this.noEchoParameters) {
26238
+ if (parameters !== void 0) {
26239
+ if (Object.hasOwn(parameters, name)) recordLogOnlyParameterValue(bag, parameters[name]);
26240
+ continue;
26241
+ }
26242
+ if (supplied !== void 0 && Object.hasOwn(supplied, name)) {
26243
+ const value = supplied[name];
26244
+ if (!this.options.maskedParameters?.has(name)) recordLogOnlyParameterValue(bag, value);
26245
+ continue;
26246
+ }
26247
+ const definition = Object.hasOwn(section, name) ? section[name] : void 0;
26248
+ if (typeof definition?.Type === "string" && definition.Type.startsWith("AWS::SSM::")) continue;
26249
+ if (definition?.Default !== void 0) recordLogOnlyParameterValue(bag, definition.Default);
26250
+ }
26251
+ return bag;
26252
+ }
25216
26253
  async valuesFor(logicalId, record) {
25217
26254
  const masked = maskedNoEchoCoordinates(record.properties, noEchoLeavesOf(record));
25218
26255
  if (masked.length === 0) return void 0;
@@ -25287,8 +26324,10 @@ var TemplateNoEchoReresolver = class TemplateNoEchoReresolver {
25287
26324
  const parameters0 = await this.boundParameters();
25288
26325
  const rowTemplate = this.options.template.Resources?.[logicalId];
25289
26326
  const passedClasses = parameters0 === void 0 ? void 0 : await classifyPassedParameters(rowTemplate?.Properties?.Parameters, this.inputSources(parameters0)).catch(() => void 0);
26327
+ const printingSeed = await this.printingNoEchoValues().catch(() => void 0);
25290
26328
  return new TemplateNoEchoReresolver({
25291
26329
  ...passedClasses !== void 0 && { passedClasses },
26330
+ ...printingSeed !== void 0 && { printingSeed },
25292
26331
  template: child.template,
25293
26332
  stackName: childStackName,
25294
26333
  region: this.options.region,
@@ -28731,347 +29770,6 @@ async function reserveStackCreateToken(options) {
28731
29770
  };
28732
29771
  }
28733
29772
 
28734
- //#endregion
28735
- //#region src/deployment/inline-policy-claims.ts
28736
- function isInlinePolicyClaimedByCompletedWriter(args, kind, principal, policyName) {
28737
- const { selfLogicalId, writers, changes, stateResources } = args;
28738
- for (const [lid, write] of writers) {
28739
- if (lid === selfLogicalId || !Object.hasOwn(stateResources, lid)) continue;
28740
- const record = stateResources[lid];
28741
- if (record.provisionedBy === "cc-api") continue;
28742
- const props = record.properties ?? {};
28743
- if (record.resourceType === "AWS::IAM::Policy") {
28744
- if (!sameIamName(record.physicalId, policyName)) continue;
28745
- const listed = props[POLICY_LIST_FIELDS[kind]];
28746
- if (Array.isArray(listed) && listed.some((p) => sameIamName(p, principal))) return true;
28747
- continue;
28748
- }
28749
- if (!Object.hasOwn(PRINCIPAL_KINDS, record.resourceType)) continue;
28750
- if (PRINCIPAL_KINDS[record.resourceType] !== kind) continue;
28751
- if (!sameIamName(record.physicalId, principal)) continue;
28752
- if (write !== "create" && !ownPoliciesChange(changes.get(lid))) continue;
28753
- const policies = props["Policies"];
28754
- if (!Array.isArray(policies)) continue;
28755
- if (policies.some((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && sameIamName(entry["PolicyName"], policyName))) return true;
28756
- }
28757
- return false;
28758
- }
28759
- var RollbackInlinePolicyWriters = class {
28760
- entries = /* @__PURE__ */ new Map();
28761
- removals = /* @__PURE__ */ new Map();
28762
- unsettled = /* @__PURE__ */ new Map();
28763
- notePending(ops) {
28764
- for (const op of ops) if (!this.unsettled.has(op)) this.unsettled.set(op, {
28765
- logicalId: op.logicalId,
28766
- state: "pending"
28767
- });
28768
- }
28769
- noteOutcome(op, completed) {
28770
- if (!completed) {
28771
- this.unsettled.set(op, {
28772
- logicalId: op.logicalId,
28773
- state: "failed"
28774
- });
28775
- return;
28776
- }
28777
- for (const [key, entry] of this.unsettled) if (key === op || entry.logicalId === op.logicalId) this.unsettled.delete(key);
28778
- }
28779
- record(logicalId, write, record, policiesChanged, via) {
28780
- if (via === "cc-api") {
28781
- this.entries.delete(logicalId);
28782
- return;
28783
- }
28784
- this.entries.set(logicalId, {
28785
- write,
28786
- record,
28787
- policiesChanged
28788
- });
28789
- }
28790
- claimedFor(resourceType, logicalId, stateResources) {
28791
- if (resourceType !== "AWS::IAM::Policy" && !Object.hasOwn(PRINCIPAL_KINDS, resourceType)) return;
28792
- return (kind, principal, policyName) => {
28793
- const writers = /* @__PURE__ */ new Map();
28794
- const changes = /* @__PURE__ */ new Map();
28795
- for (const [lid, entry] of this.entries) {
28796
- if (!Object.hasOwn(stateResources, lid) || stateResources[lid] !== entry.record) continue;
28797
- writers.set(lid, entry.write);
28798
- if (entry.policiesChanged) changes.set(lid, {
28799
- logicalId: lid,
28800
- changeType: "UPDATE",
28801
- resourceType: entry.record.resourceType,
28802
- propertyChanges: [{
28803
- path: "Policies",
28804
- oldValue: void 0,
28805
- newValue: void 0,
28806
- requiresReplacement: false
28807
- }]
28808
- });
28809
- }
28810
- const claimed = isInlinePolicyClaimedByCompletedWriter({
28811
- selfLogicalId: logicalId,
28812
- writers,
28813
- changes,
28814
- stateResources
28815
- }, kind, principal, policyName);
28816
- if (!claimed) {
28817
- const key = removalKey(kind, principal, policyName);
28818
- const noted = this.removals.get(key) ?? {
28819
- kind,
28820
- principal,
28821
- policyName,
28822
- removers: /* @__PURE__ */ new Map()
28823
- };
28824
- noted.removers.set(logicalId, stateResources[logicalId]);
28825
- this.removals.set(key, noted);
28826
- }
28827
- return claimed;
28828
- };
28829
- }
28830
- takeHeldRemovals(stateResources) {
28831
- const held = [];
28832
- for (const [key, { kind, principal, policyName, removers }] of this.removals) {
28833
- const { holders, unreadable } = inlinePolicyHolders(stateResources, kind, principal, policyName);
28834
- const others = holders.filter((h) => !removers.has(h.logicalId) || stateResources[h.logicalId] !== removers.get(h.logicalId));
28835
- if (others.length === 0) continue;
28836
- this.removals.delete(key);
28837
- const open = new Set([...this.unsettled.values()].map((u) => u.logicalId));
28838
- const unsettled = [...new Set(others.map((h) => h.logicalId))].filter((id) => open.has(id));
28839
- held.push({
28840
- kind,
28841
- holders: others,
28842
- unreadable,
28843
- unsettled
28844
- });
28845
- }
28846
- return held;
28847
- }
28848
- };
28849
- function inlinePolicyHolders(stateResources, kind, principal, policyName) {
28850
- const holders = [];
28851
- const unreadable = [];
28852
- const unnamed = (v) => typeof v !== "string" || !IAM_NAME.test(v);
28853
- for (const [logicalId, record] of Object.entries(stateResources)) {
28854
- if (record === null || typeof record !== "object") continue;
28855
- const props = record.properties ?? {};
28856
- if (record.resourceType === "AWS::IAM::Policy") {
28857
- const nameMatches = sameIamName(record.physicalId, policyName);
28858
- if (!nameMatches && !unnamed(record.physicalId)) continue;
28859
- const listed = props[POLICY_LIST_FIELDS[kind]];
28860
- const entries = Array.isArray(listed) ? listed : [];
28861
- const named = entries.find((p) => sameIamName(p, principal));
28862
- if (nameMatches && typeof named === "string") holders.push({
28863
- logicalId,
28864
- principal: named,
28865
- policyName: record.physicalId,
28866
- document: props["PolicyDocument"]
28867
- });
28868
- else if (named !== void 0 || entries.some(unnamed)) unreadable.push(logicalId);
28869
- continue;
28870
- }
28871
- if (!Object.hasOwn(PRINCIPAL_KINDS, record.resourceType)) continue;
28872
- if (PRINCIPAL_KINDS[record.resourceType] !== kind) continue;
28873
- const principalMatches = sameIamName(record.physicalId, principal);
28874
- if (!principalMatches && !unnamed(record.physicalId)) continue;
28875
- const policies = props["Policies"];
28876
- if (!Array.isArray(policies)) continue;
28877
- for (const entry of policies) {
28878
- if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue;
28879
- const name = entry["PolicyName"];
28880
- if (principalMatches && sameIamName(name, policyName)) holders.push({
28881
- logicalId,
28882
- principal: record.physicalId,
28883
- policyName: name,
28884
- document: entry["PolicyDocument"]
28885
- });
28886
- else if (unnamed(name) || sameIamName(name, policyName)) unreadable.push(logicalId);
28887
- }
28888
- }
28889
- return {
28890
- holders,
28891
- unreadable: [...new Set(unreadable)]
28892
- };
28893
- }
28894
- function sameIamName(a, b) {
28895
- return typeof a === "string" && IAM_NAME.test(a) && a.toLowerCase() === b.toLowerCase();
28896
- }
28897
- function removalKey(kind, principal, policyName) {
28898
- return JSON.stringify([
28899
- kind,
28900
- principal.toLowerCase(),
28901
- policyName.toLowerCase()
28902
- ]);
28903
- }
28904
- const IAM_NAME = /^[\w+=,.@-]+$/;
28905
- const POLICY_LIST_FIELDS = {
28906
- role: "Roles",
28907
- group: "Groups",
28908
- user: "Users"
28909
- };
28910
- const PRINCIPAL_KINDS = {
28911
- "AWS::IAM::Role": "role",
28912
- "AWS::IAM::Group": "group",
28913
- "AWS::IAM::User": "user"
28914
- };
28915
- function isInlinePolicyPrincipalType(resourceType) {
28916
- return Object.hasOwn(PRINCIPAL_KINDS, resourceType);
28917
- }
28918
- function principalKindOf(resourceType) {
28919
- return Object.hasOwn(PRINCIPAL_KINDS, resourceType) ? PRINCIPAL_KINDS[resourceType] : void 0;
28920
- }
28921
- const ANY = "*";
28922
- const PRINCIPAL_NAME_FIELDS = {
28923
- role: "RoleName",
28924
- group: "GroupName",
28925
- user: "UserName"
28926
- };
28927
- function nameKey(value) {
28928
- return typeof value === "string" && IAM_NAME.test(value) ? value.toLowerCase() : ANY;
28929
- }
28930
- function templatePrincipalKeys(entry, kind, templateResources, stateResources) {
28931
- if (typeof entry === "string") return [nameKey(entry)];
28932
- const ref = typeof entry === "object" && entry !== null && !Array.isArray(entry) ? entry["Ref"] : void 0;
28933
- if (typeof ref !== "string" || !Object.hasOwn(templateResources, ref)) return [ANY];
28934
- const target = templateResources[ref];
28935
- if (principalKindOf(target.Type) !== kind) return [ANY];
28936
- return principalSelfKeys(ref, kind, target, stateResources);
28937
- }
28938
- function principalSelfKeys(logicalId, kind, template, stateResources) {
28939
- const keys = [`ref:${logicalId}`];
28940
- const declared = template?.Properties?.[PRINCIPAL_NAME_FIELDS[kind]];
28941
- const declaredKey = nameKey(declared);
28942
- if (declaredKey !== ANY) keys.push(declaredKey);
28943
- const record = Object.hasOwn(stateResources, logicalId) ? stateResources[logicalId] : void 0;
28944
- if (record !== void 0 && principalKindOf(record.resourceType) === kind) {
28945
- const recordedKey = nameKey(record.physicalId);
28946
- if (recordedKey !== ANY) keys.push(recordedKey);
28947
- }
28948
- return keys;
28949
- }
28950
- function policiesNames(policies) {
28951
- if (policies === void 0 || policies === null) return [];
28952
- if (!Array.isArray(policies)) return [ANY];
28953
- return policies.map((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) ? nameKey(entry["PolicyName"]) : ANY);
28954
- }
28955
- function inlinePolicyClaimsOf(logicalId, change, templateResources, stateResources) {
28956
- const template = Object.hasOwn(templateResources, logicalId) ? templateResources[logicalId] : void 0;
28957
- const record = Object.hasOwn(stateResources, logicalId) ? stateResources[logicalId] : void 0;
28958
- const recorded = record?.resourceType === change.resourceType ? record : void 0;
28959
- const claims = [];
28960
- const cross = (kind, principals, names) => {
28961
- for (const principal of new Set(principals)) for (const name of new Set(names)) claims.push({
28962
- kind,
28963
- principal,
28964
- name
28965
- });
28966
- };
28967
- if (change.resourceType === "AWS::IAM::Policy") {
28968
- const desired = template?.Properties ?? {};
28969
- const old = recorded?.properties ?? {};
28970
- const names = [];
28971
- if (desired["PolicyName"] !== void 0) names.push(nameKey(desired["PolicyName"]));
28972
- if (old["PolicyName"] !== void 0) names.push(nameKey(old["PolicyName"]));
28973
- if (recorded !== void 0) names.push(nameKey(typeof recorded.physicalId === "string" ? recorded.physicalId.split(":")[0] : recorded.physicalId));
28974
- if (names.length === 0) return claims;
28975
- for (const kind of [
28976
- "role",
28977
- "group",
28978
- "user"
28979
- ]) {
28980
- const field = POLICY_LIST_FIELDS[kind];
28981
- const principals = [];
28982
- const listed = desired[field];
28983
- if (Array.isArray(listed)) for (const entry of listed) principals.push(...templatePrincipalKeys(entry, kind, templateResources, stateResources));
28984
- else if (listed !== void 0) principals.push(ANY);
28985
- const held = old[field];
28986
- if (Array.isArray(held)) principals.push(...held.map(nameKey));
28987
- else if (held !== void 0 && held !== null) principals.push(ANY);
28988
- cross(kind, principals, names);
28989
- }
28990
- return claims;
28991
- }
28992
- const kind = principalKindOf(change.resourceType);
28993
- if (kind === void 0) return claims;
28994
- if (!(change.changeType === "CREATE" || (change.propertyChanges ?? []).some((c) => c.requiresReplacement) || ownPoliciesChange(change))) return claims;
28995
- cross(kind, principalSelfKeys(logicalId, kind, template, stateResources), [...policiesNames(template?.Properties?.["Policies"]), ...policiesNames(recorded?.properties?.["Policies"])]);
28996
- return claims;
28997
- }
28998
- function orderInlinePolicyWriters(args) {
28999
- const { writes, changes, templateResources, stateResources, dependencies, rank } = args;
29000
- const writers = writes.filter((id) => {
29001
- const type = changes.get(id)?.resourceType;
29002
- return type === "AWS::IAM::Policy" || type !== void 0 && isInlinePolicyPrincipalType(type);
29003
- });
29004
- if (writers.length < 2) return [];
29005
- const exact = /* @__PURE__ */ new Map();
29006
- const loose = [];
29007
- const all = [];
29008
- for (const id of writers) for (const claim of inlinePolicyClaimsOf(id, changes.get(id), templateResources, stateResources)) {
29009
- all.push({
29010
- id,
29011
- claim
29012
- });
29013
- if (claim.principal === ANY || claim.name === ANY) {
29014
- loose.push({
29015
- id,
29016
- claim
29017
- });
29018
- continue;
29019
- }
29020
- const key = JSON.stringify([
29021
- claim.kind,
29022
- claim.principal,
29023
- claim.name
29024
- ]);
29025
- const ids = exact.get(key) ?? /* @__PURE__ */ new Set();
29026
- ids.add(id);
29027
- exact.set(key, ids);
29028
- }
29029
- const principalRows = new Set(writers.filter((id) => isInlinePolicyPrincipalType(changes.get(id).resourceType)));
29030
- const pairs = /* @__PURE__ */ new Map();
29031
- const pair = (a, b) => {
29032
- if (a === b || principalRows.has(a) && principalRows.has(b)) return;
29033
- const [x, y] = rank(a) < rank(b) || rank(a) === rank(b) && a < b ? [a, b] : [b, a];
29034
- pairs.set(JSON.stringify([x, y]), [x, y]);
29035
- };
29036
- for (const ids of exact.values()) {
29037
- const list = [...ids];
29038
- for (let i = 0; i < list.length; i++) for (let j = i + 1; j < list.length; j++) pair(list[i], list[j]);
29039
- }
29040
- const meets = (a, b) => a === ANY || b === ANY || a === b;
29041
- for (const { id, claim } of loose) for (const other of all) {
29042
- if (other.claim.kind !== claim.kind) continue;
29043
- if (meets(claim.principal, other.claim.principal) && meets(claim.name, other.claim.name)) pair(id, other.id);
29044
- }
29045
- if (pairs.size === 0) return [];
29046
- const reaches = (from, to) => {
29047
- const seen = /* @__PURE__ */ new Set();
29048
- const stack = [from];
29049
- while (stack.length > 0) {
29050
- const id = stack.pop();
29051
- if (id === to) return true;
29052
- if (seen.has(id)) continue;
29053
- seen.add(id);
29054
- for (const dep of dependencies.get(id) ?? []) stack.push(dep);
29055
- }
29056
- return false;
29057
- };
29058
- const added = [];
29059
- for (const [before, after] of pairs.values()) {
29060
- if (reaches(after, before) || reaches(before, after)) continue;
29061
- const deps = dependencies.get(after) ?? /* @__PURE__ */ new Set();
29062
- deps.add(before);
29063
- dependencies.set(after, deps);
29064
- added.push({
29065
- before,
29066
- after
29067
- });
29068
- }
29069
- return added;
29070
- }
29071
- function ownPoliciesChange(change) {
29072
- return (change?.propertyChanges ?? []).some((c) => c.path === "Policies" && c.inPlacePropagated !== true && c.replacementPropagated !== true);
29073
- }
29074
-
29075
29773
  //#endregion
29076
29774
  //#region src/analyzer/destructive-changes.ts
29077
29775
  const IGNORED_RESOURCE_TYPES = /* @__PURE__ */ new Set(["AWS::CDK::Metadata"]);
@@ -29993,14 +30691,43 @@ function secretNamedRecordNeedles(resources, secrets, bag = /* @__PURE__ */ new
29993
30691
  return bag;
29994
30692
  }
29995
30693
  function secretNamePrintingBag(logicalId, resources) {
29996
- const bag = /* @__PURE__ */ new Map();
29997
- const record = Object.hasOwn(resources, logicalId) ? resources[logicalId] : void 0;
29998
- for (const needle of secretNameNeedlesOf(logicalId, record, void 0) ?? []) recordLogOnlyValue(bag, needle);
29999
- for (const needle of secretNamesReadBy(logicalId, record, resources)) recordLogOnlyValue(bag, needle);
30000
- return bag;
30694
+ return secretNamePrintingBags(resources, void 0)(logicalId);
30695
+ }
30696
+ function secretNamePrintingBags(resources, noEchoValues) {
30697
+ const secrets = noEchoValues !== void 0 && hasMaskableValues(noEchoValues) ? noEchoValues : void 0;
30698
+ const judged = /* @__PURE__ */ new Map();
30699
+ const needlesOf = (logicalId, record) => {
30700
+ const hit = judged.get(logicalId);
30701
+ if (hit !== void 0 && hit.record === record) return hit.needles;
30702
+ const needles = secretNameNeedlesOf(logicalId, record, secrets, { embedded: void 0 });
30703
+ judged.set(logicalId, {
30704
+ record,
30705
+ needles
30706
+ });
30707
+ return needles;
30708
+ };
30709
+ return (logicalId) => {
30710
+ const bag = /* @__PURE__ */ new Map();
30711
+ if (secrets !== void 0) carryLogOnlyValues(secrets, bag);
30712
+ const record = Object.hasOwn(resources, logicalId) ? resources[logicalId] : void 0;
30713
+ for (const needle of needlesOf(logicalId, record) ?? []) recordLogOnlyValue(bag, needle);
30714
+ const leaves = [...wholeStringLeavesOf(record?.properties)].filter((leaf) => leaf !== "");
30715
+ if (leaves.length === 0) return bag;
30716
+ for (const [otherId, other] of Object.entries(resources)) {
30717
+ if (otherId === logicalId) continue;
30718
+ for (const needle of needlesOf(otherId, other) ?? []) if (leavesHoldNeedle(leaves, needle)) recordLogOnlyValue(bag, needle);
30719
+ }
30720
+ return bag;
30721
+ };
30001
30722
  }
30002
- function journaledOrphanPrintingBag(ops, stateResources) {
30723
+ function journaledOrphanPrintingBag(ops, stateResources, noEchoValues) {
30003
30724
  const bag = /* @__PURE__ */ new Map();
30725
+ const secrets = noEchoValues !== void 0 && hasMaskableValues(noEchoValues) ? noEchoValues : void 0;
30726
+ if (secrets !== void 0) carryLogOnlyValues(secrets, bag);
30727
+ const judge = {
30728
+ secrets,
30729
+ embedded: void 0
30730
+ };
30004
30731
  for (const op of ops) {
30005
30732
  const record = {
30006
30733
  resourceType: op.resourceType,
@@ -30009,9 +30736,9 @@ function journaledOrphanPrintingBag(ops, stateResources) {
30009
30736
  };
30010
30737
  const replaced = Object.hasOwn(stateResources, op.logicalId) ? stateResources[op.logicalId] : void 0;
30011
30738
  for (const needle of [
30012
- ...secretNameNeedlesOf(op.logicalId, record, void 0) ?? [],
30013
- ...secretNameNeedlesOf(op.logicalId, replaced, void 0) ?? [],
30014
- ...secretNamesReadBy(op.logicalId, record, stateResources)
30739
+ ...secretNameNeedlesOf(op.logicalId, record, secrets, judge) ?? [],
30740
+ ...secretNameNeedlesOf(op.logicalId, replaced, secrets, judge) ?? [],
30741
+ ...secretNamesReadBy(op.logicalId, record, stateResources, () => judge)
30015
30742
  ]) recordLogOnlyValue(bag, needle);
30016
30743
  }
30017
30744
  return bag;
@@ -30031,13 +30758,15 @@ function completedReplayEntries(ops) {
30031
30758
  attemptedProperties: op.previousState.properties
30032
30759
  }]]);
30033
30760
  }
30034
- function orphanRecordsPrintingBag(records) {
30761
+ function orphanRecordsPrintingBag(records, noEchoValues) {
30035
30762
  const bag = /* @__PURE__ */ new Map();
30763
+ const secrets = noEchoValues !== void 0 && hasMaskableValues(noEchoValues) ? noEchoValues : void 0;
30764
+ if (secrets !== void 0) carryLogOnlyValues(secrets, bag);
30036
30765
  for (const entry of records) {
30037
30766
  if (entry === null || typeof entry !== "object") continue;
30038
30767
  const { logicalId, state } = entry;
30039
30768
  if (typeof logicalId !== "string" || state === null || typeof state !== "object") continue;
30040
- for (const needle of secretNameNeedlesOf(logicalId, state, void 0) ?? []) recordLogOnlyValue(bag, needle);
30769
+ for (const needle of secretNameNeedlesOf(logicalId, state, secrets, { embedded: void 0 }) ?? []) recordLogOnlyValue(bag, needle);
30041
30770
  }
30042
30771
  return bag;
30043
30772
  }
@@ -30147,7 +30876,7 @@ function withNoEchoDefaultsMasked(parameters) {
30147
30876
  const masked = Object.create(null);
30148
30877
  for (const [name, decl] of Object.entries(parameters)) {
30149
30878
  const body = decl;
30150
- masked[name] = typeof body === "object" && body !== null && body["NoEcho"] === true && "Default" in body ? {
30879
+ masked[name] = typeof body === "object" && body !== null && declaresNoEcho(body) && "Default" in body ? {
30151
30880
  ...body,
30152
30881
  Default: NO_ECHO_DEFAULT_MASK
30153
30882
  } : decl;
@@ -30359,7 +31088,7 @@ function noEchoParameterValueSeed(parameters, values, inherited, userParameters)
30359
31088
  if (values === void 0) return seed;
30360
31089
  for (const [name, value] of Object.entries(values)) {
30361
31090
  if (isWholeDynamicReferenceValue(value)) continue;
30362
- if (parameters?.[name]?.NoEcho === true) {
31091
+ if (parameters !== void 0 && declaresNoEcho(parameters[name])) {
30363
31092
  const type = parameters[name]?.Type;
30364
31093
  const ssmTyped = typeof type === "string" && type.startsWith("AWS::SSM::Parameter::Value<");
30365
31094
  const spelled = Object.prototype.hasOwnProperty.call(userParameters ?? {}, name) ? userParameters?.[name] : parameters[name]?.Default;
@@ -31147,13 +31876,52 @@ async function resolveLeafByRegion(leaf, propertyPath, logicalId, execCtx, resol
31147
31876
  }
31148
31877
  return out + leaf.slice(cursor);
31149
31878
  }
31150
- function redactRollbackRecord(record, secrets, journaledProps) {
31879
+ function redactRollbackRecord(record, secrets, journaledProps, journaledAttributes) {
31151
31880
  if (secrets.size === 0) return record;
31152
31881
  const positioned = journaledProps === void 0 ? record : {
31153
31882
  ...record,
31154
31883
  properties: redactSecretsForState(record.properties, secrets, journaledProps, STATE_DERIVED_RULES)
31155
31884
  };
31156
- return scrubResourceRecord(positioned, secrets);
31885
+ return keepPersistedPlainRecordLeaves(scrubResourceRecord(positioned, secrets), record, {
31886
+ properties: journaledProps,
31887
+ attributes: journaledAttributes
31888
+ });
31889
+ }
31890
+ function keepPersistedPlainRecordLeaves(scrubbed, raw, persisted) {
31891
+ const properties = keepPersistedPlainLeaves(scrubbed.properties, raw.properties, persisted.properties);
31892
+ const attributes = scrubbed.attributes === void 0 ? void 0 : keepPersistedPlainLeaves(scrubbed.attributes, raw.attributes, persisted.attributes);
31893
+ if (properties === scrubbed.properties && attributes === scrubbed.attributes) return scrubbed;
31894
+ return {
31895
+ ...scrubbed,
31896
+ properties,
31897
+ ...attributes !== void 0 && { attributes }
31898
+ };
31899
+ }
31900
+ function keepPersistedPlainLeaves(redacted, raw, persisted) {
31901
+ if (typeof raw === "string") return typeof persisted === "string" && raw === persisted && redacted !== "***" && dynamicReferenceTokens(persisted).length === 0 ? persisted : redacted;
31902
+ if (Array.isArray(raw)) {
31903
+ if (!Array.isArray(persisted) || !Array.isArray(redacted)) return redacted;
31904
+ if (redacted.length !== raw.length) return redacted;
31905
+ let out;
31906
+ for (let i = 0; i < redacted.length; i++) {
31907
+ const kept = keepPersistedPlainLeaves(redacted[i], raw[i], persisted[i]);
31908
+ if (kept !== redacted[i]) (out ??= [...redacted])[i] = kept;
31909
+ }
31910
+ return out ?? redacted;
31911
+ }
31912
+ if (!isPlainRecord$1(raw) || !isPlainRecord$1(persisted) || !isPlainRecord$1(redacted)) return redacted;
31913
+ let out;
31914
+ for (const key of Object.keys(redacted)) {
31915
+ if (!hasOwnKey(raw, key) || !hasOwnKey(persisted, key)) continue;
31916
+ const kept = keepPersistedPlainLeaves(redacted[key], raw[key], persisted[key]);
31917
+ if (kept === redacted[key]) continue;
31918
+ out ??= { ...redacted };
31919
+ out[key] = kept;
31920
+ }
31921
+ return out ?? redacted;
31922
+ }
31923
+ function isPlainRecord$1(value) {
31924
+ return typeof value === "object" && value !== null && !Array.isArray(value) && hasPlainPrototype$1(value);
31157
31925
  }
31158
31926
 
31159
31927
  //#endregion
@@ -32207,7 +32975,7 @@ async function replayRevert(s) {
32207
32975
  }
32208
32976
  ], op.logicalId, logger, isInterrupted, secrets, mask));
32209
32977
  if (revertResult) recordNoEchoAttributeValues(revertResult, secrets, desiredProps);
32210
- stateResources[op.logicalId] = maskRestoredNoEchoRecord(redactRollbackRecord(recordAfterRollbackUpdate(previousState, revertResult), secrets, previousState.properties), previousState, noEcho.substituted);
32978
+ stateResources[op.logicalId] = maskRestoredNoEchoRecord(redactRollbackRecord(recordAfterRollbackUpdate(previousState, revertResult), secrets, previousState.properties, previousState.attributes), previousState, noEcho.substituted);
32211
32979
  if (updatePartialReason(revertResult) === void 0) inlinePolicyWriters.record(op.logicalId, "update", stateResources[op.logicalId], !deepEqual$1(previousState.properties?.["Policies"], current.properties?.["Policies"]), revertVia);
32212
32980
  const rollbackPartial = updatePartialReason(revertResult);
32213
32981
  if (rollbackPartial !== void 0) logger.warn(mask(` Rollback: ${safe(op.logicalId)} restored, ${updatePartialMessage(rollbackPartial)}`));
@@ -32406,7 +33174,7 @@ async function replayReverseReplacement(s) {
32406
33174
  physicalId: createResult.physicalId,
32407
33175
  attributes: createResult.attributes ?? {},
32408
33176
  properties: recordedPropertiesAfterReplayCreate(prevRecord, createResult)
32409
- }, secrets, prevRecord.properties);
33177
+ }, secrets, prevRecord.properties, prevRecord.attributes);
32410
33178
  if (!adoptedLiveNewResource) inlinePolicyWriters.record(op.logicalId, "create", stateResources[op.logicalId], false, createProvisionedBy);
32411
33179
  await afterOp?.(op.logicalId);
32412
33180
  let survivorReason;
@@ -32577,12 +33345,12 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
32577
33345
  inlinePolicyWriters.notePending(operations);
32578
33346
  markDeleteFirstBlocked(operations, options.failedOperations);
32579
33347
  const { createOps, otherOps } = partitionOps(operations);
32580
- for (let i = otherOps.length - 1; i >= 0; i--) {
33348
+ for (const op of orderInlinePolicyReversals([...otherOps].reverse(), stateResources)) {
32581
33349
  if (options.isInterrupted?.()) {
32582
33350
  result.interrupted = true;
32583
33351
  break;
32584
33352
  }
32585
- await replaySingle(otherOps[i], stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.onOrphan, inlinePolicyWriters, options.afterOp, options.isInterrupted);
33353
+ await replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.onOrphan, inlinePolicyWriters, options.afterOp, options.isInterrupted);
32586
33354
  }
32587
33355
  if (!result.interrupted && createOps.length > 0) {
32588
33356
  const sorted = sortRollbackCreates(createOps, stateResources);
@@ -32966,7 +33734,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
32966
33734
  }
32967
33735
  ], op.logicalId, logger, options.isInterrupted, secrets, mask));
32968
33736
  if (revertFailedResult) recordNoEchoAttributeValues(revertFailedResult, secrets, desiredProps);
32969
- stateResources[op.logicalId] = maskRestoredNoEchoRecord(redactRollbackRecord(recordAfterRollbackUpdate(prev, revertFailedResult), secrets, prev.properties), prev, noEcho.substituted);
33737
+ stateResources[op.logicalId] = maskRestoredNoEchoRecord(redactRollbackRecord(recordAfterRollbackUpdate(prev, revertFailedResult), secrets, prev.properties, prev.attributes), prev, noEcho.substituted);
32970
33738
  if (updatePartialReason(revertFailedResult) === void 0) inlinePolicyWriters.record(op.logicalId, "update", stateResources[op.logicalId], !deepEqual$1(prev.properties?.["Policies"], (op.attemptedProperties ?? current.properties)?.["Policies"]), revertVia);
32971
33739
  const revertFailedPartial = updatePartialReason(revertFailedResult);
32972
33740
  if (revertFailedPartial !== void 0) logger.warn(mask(` Rollback: ${safe(op.logicalId)} reverted, ${updatePartialMessage(revertFailedPartial)}`));
@@ -33124,7 +33892,7 @@ async function deleteJournaledOrphans(orphans, stateResources, stackName, ctx, o
33124
33892
  const inlinePolicyWriters = new RollbackInlinePolicyWriters();
33125
33893
  const failedIds = total.failedLogicalIds;
33126
33894
  const record = ctx.recordEvent;
33127
- const printing = journaledOrphanPrintingBag(orphans.segments.flatMap(({ ops, companions }) => [...companions ?? [], ...ops]), stateResources);
33895
+ const printing = journaledOrphanPrintingBag(orphans.segments.flatMap(({ ops, companions }) => [...companions ?? [], ...ops]), stateResources, options.noEchoValues);
33128
33896
  const maskedCtx = record === void 0 ? ctx : {
33129
33897
  ...ctx,
33130
33898
  recordEvent: (event) => record(maskEventTextWithBoundBags(event))
@@ -33936,11 +34704,14 @@ function redactOperationsForJournal(operations) {
33936
34704
  if (next.attemptedProperties) next.attemptedProperties = byPosition(redactSecretsForState(markSameGenerationBag({ ...next.attemptedProperties }), ownSecrets, templateProps));
33937
34705
  if (next.previousState) {
33938
34706
  const previous = next.previousState;
33939
- next.previousState = this.applyNoEchoPersist(op.logicalId, previous, scrubResourceRecord(previous, ownSecrets, void 0, STATE_SOURCED_READBACK_RULES), void 0, {}, void 0, true);
34707
+ const adopted = adoptedOrphanRecords.get(this);
34708
+ const loaded = adopted?.has(op.logicalId) ? adopted.get(op.logicalId) : previous;
34709
+ next.previousState = this.applyNoEchoPersist(op.logicalId, previous, keepPersistedPlainRecordLeaves(scrubResourceRecord(previous, ownSecrets, void 0, STATE_SOURCED_READBACK_RULES), previous, loaded ?? {}), void 0, {}, void 0, true);
33940
34710
  }
33941
34711
  return next;
33942
34712
  });
33943
34713
  }
34714
+ const adoptedOrphanRecords = /* @__PURE__ */ new WeakMap();
33944
34715
  async function adoptRollbackOrphans(currentState, effectiveTemplate) {
33945
34716
  const records = currentState.orphans ?? [];
33946
34717
  const named = orphanRecordsPrintingBag(records);
@@ -33967,8 +34738,11 @@ async function adoptRollbackOrphans(currentState, effectiveTemplate) {
33967
34738
  logger: { debug: (m) => this.logger.debug(m) }
33968
34739
  }));
33969
34740
  for (const notice of plan.notices) this.logger.info(maskSecretsInText(notice, named));
34741
+ const adoptedFrom = /* @__PURE__ */ new Map();
34742
+ adoptedOrphanRecords.set(this, adoptedFrom);
33970
34743
  if (plan.refusals.length > 0) throw new Error(`Deploy refused — cdkd left ${plan.refusals.length} resource(s) in AWS that it cannot safely re-adopt:\n ${plan.refusals.map((r) => maskSecretsInText(r, named)).join("\n ")}`);
33971
34744
  for (const [logicalId, record] of Object.entries(plan.adopted)) {
34745
+ adoptedFrom.set(logicalId, records.findLast((r) => r.logicalId === logicalId)?.state);
33972
34746
  currentState.resources[logicalId] = record;
33973
34747
  this.logger.info(`Adopting ${displayIdent(logicalId)} (${displayIdent(record.resourceType)}) left in AWS by an earlier rollback as ${displaySafe(maskSecretsInText(record.physicalId, named))}`);
33974
34748
  }
@@ -34582,6 +35356,20 @@ async function drainObservedCaptures(stateResources) {
34582
35356
  }
34583
35357
  return installed;
34584
35358
  }
35359
+ const STANDALONE_SIBLING = {
35360
+ Roles: {
35361
+ type: "AWS::IAM::RolePolicy",
35362
+ field: "RoleName"
35363
+ },
35364
+ Users: {
35365
+ type: "AWS::IAM::UserPolicy",
35366
+ field: "UserName"
35367
+ },
35368
+ Groups: {
35369
+ type: "AWS::IAM::GroupPolicy",
35370
+ field: "GroupName"
35371
+ }
35372
+ };
34585
35373
  async function buildObservedCaptureSiblings(resourceType, capturedLogicalId, capturedPhysicalId, template, stateResources, stackName, parameterValues, conditions) {
34586
35374
  if (this.options.captureObservedState !== true) return void 0;
34587
35375
  const attachmentField = resourceType === "AWS::IAM::Role" ? "Roles" : resourceType === "AWS::IAM::User" ? "Users" : resourceType === "AWS::IAM::Group" ? "Groups" : void 0;
@@ -34591,11 +35379,12 @@ async function buildObservedCaptureSiblings(resourceType, capturedLogicalId, cap
34591
35379
  let resolverContext;
34592
35380
  const isRefTo = (value, logicalId) => typeof value === "object" && value !== null && !Array.isArray(value) && value["Ref"] === logicalId;
34593
35381
  const siblings = {};
35382
+ const standaloneType = STANDALONE_SIBLING[attachmentField];
34594
35383
  for (const [lid, res] of Object.entries(resources)) {
34595
35384
  if (lid === capturedLogicalId) continue;
34596
- if (res.Type !== "AWS::IAM::Policy") continue;
35385
+ if (res.Type !== "AWS::IAM::Policy" && res.Type !== standaloneType.type) continue;
34597
35386
  const props = res.Properties ?? {};
34598
- const attachments = props[attachmentField];
35387
+ const attachments = res.Type === "AWS::IAM::Policy" ? props[attachmentField] : [props[standaloneType.field]];
34599
35388
  if (!Array.isArray(attachments)) continue;
34600
35389
  if (!attachments.some((a) => isRefTo(a, capturedLogicalId) || a === capturedPhysicalId)) continue;
34601
35390
  let policyName = props["PolicyName"];
@@ -34808,9 +35597,9 @@ function deepEqualValue(a, b) {
34808
35597
  function diffLogMasker(diffSecrets, template, parameterValues, resources) {
34809
35598
  const inherited = this.options.inheritedSecrets;
34810
35599
  const noEchoValues = /* @__PURE__ */ new Map();
34811
- const noEchoNames = new Set(Object.entries(template.Parameters ?? {}).filter(([, definition]) => definition?.NoEcho === true).map(([name]) => name));
35600
+ const noEchoNames = new Set(Object.entries(template.Parameters ?? {}).filter(([, definition]) => declaresNoEcho(definition)).map(([name]) => name));
34812
35601
  const splitDelimiters = literalSplitDelimitersOf(template, noEchoNames);
34813
- for (const [name, definition] of Object.entries(template.Parameters ?? {})) if (definition?.NoEcho === true && Object.hasOwn(parameterValues, name)) recordLogOnlyParameterValue(noEchoValues, parameterValues[name], splitDelimiters);
35602
+ for (const [name, definition] of Object.entries(template.Parameters ?? {})) if (declaresNoEcho(definition) && Object.hasOwn(parameterValues, name)) recordLogOnlyParameterValue(noEchoValues, parameterValues[name], splitDelimiters);
34814
35603
  const stateNames = /* @__PURE__ */ new Map();
34815
35604
  const union = createUnionSecretMasker([
34816
35605
  diffSecrets,
@@ -34907,7 +35696,7 @@ function refuseRedactedAttributeReads(logicalId, resourceType, context) {
34907
35696
  const producers = [...new Set(reads.map((read) => read.logicalId).filter((id) => !!id))];
34908
35697
  throw new ProvisioningError(`Cannot resolve ${reads.map((read) => read.display).join(", ")} for ${logicalId}: ${producers.map((id) => displayIdent(id)).join(", ")} declared ${reads.length === 1 ? "that attribute" : "those attributes"} NoEcho, so cdkd's recorded state holds only the redaction mask for ${reads.length === 1 ? "it" : "them"}, and cdkd does not re-run a producer to recover a value. Remedy: deploy a change to the producer in the SAME run as ${logicalId} (for a custom resource, change one of its properties, e.g. a nonce / version property, so its handler runs again and supplies the value), or stop declaring the value NoEcho.`, resourceType, logicalId);
34909
35698
  }
34910
- throw new ProvisioningError(`Cannot resolve ${reads.map((read) => read.display).join(", ")} for ${logicalId}: cdkd's recorded state holds only the redaction mask there, and the value is not recoverable from state. There are three ways a record comes to hold the mask. (1) A custom resource handler declared its response NoEcho: true — the value is generated by the handler, so cdkd has nothing to re-derive it from and must not write the literal mask to AWS. Remedies: force that custom resource to update (change one of its properties, e.g. a nonce / version property) so its handler runs again and supplies the value in this same run; or stop setting NoEcho on that response. If the value comes from ANOTHER stack, the producer and this stack must deploy in ONE run (cdkd deploy --all, or cdkd deploy '**' when either is inside a CDK Stage) with the producer's custom resource actually running — re-deploying the producer by itself does not help, because it re-masks the value on the way into its own state. (2) The value holds the Fn::Base64 encoding of a secret value (a {{resolve:...}} dynamic reference under Fn::Base64, such as EC2 UserData), which cdkd never records — so a deploy that leaves the resource or output holding it unchanged reads the mask again, and a re-import does not recover it. Remedy: have this resource build the value itself from the SECRET's own reference (the {{resolve:secretsmanager:...}} or {{resolve:ssm-secure:...}} reference, or a {{resolve:ssm:...}} of a SecureString parameter, that the encoding was made from) under its own Fn::Base64, instead of reading it from another resource's attribute or another stack's output — not by a {{resolve:ssm:...}} read of a String parameter holding the encoding, which cdkd treats as public and would record in state in the clear. (3) The resource was adopted by 'cdkd import' through the Cloud Control fallback, which records only the type's Fn::GetAtt attributes (its read-only properties plus the writable ones CloudFormation also accepts in Fn::GetAtt) and masks the rest. Either the attribute named above is not one of them — CloudFormation would reject an Fn::GetAtt naming it too, so stop reading it — or cdkd could not read that schema and masked the whole model, which the import warned about when it happened. If that warning named a missing cloudformation:DescribeType permission, grant it first. See https://github.com/go-to-k/cdkd/issues/2449. ${DeployEngine.maskedRecordRemedyFor(reads, context.resources, true)}`, resourceType, logicalId);
35699
+ throw new ProvisioningError(`Cannot resolve ${reads.map((read) => read.display).join(", ")} for ${logicalId}: cdkd's recorded state holds only the redaction mask there, and the value is not recoverable from state. There are three ways a record comes to hold the mask. (1) A custom resource handler declared its response NoEcho: true — the value is generated by the handler, so cdkd has nothing to re-derive it from and must not write the literal mask to AWS. Remedies: force that custom resource to update (change one of its properties, e.g. a nonce / version property) so its handler runs again and supplies the value in this same run; or stop setting NoEcho on that response. If the value comes from ANOTHER stack, the producer and this stack must deploy in ONE run (cdkd deploy --all, or cdkd deploy '**' when either is inside a CDK Stage) with the producer's custom resource actually running — re-deploying the producer by itself does not help, because it re-masks the value on the way into its own state. (2) The value holds the Fn::Base64 encoding of a secret value (a {{resolve:...}} dynamic reference under Fn::Base64, such as EC2 UserData), which cdkd never records — so a deploy that leaves the resource or output holding it unchanged reads the mask again, and a re-import does not recover it. Remedy: have this resource build the value itself from the SECRET's own reference (the {{resolve:secretsmanager:...}} or {{resolve:ssm-secure:...}} reference, or a {{resolve:ssm:...}} of a SecureString parameter, that the encoding was made from) under its own Fn::Base64, instead of reading it from another resource's attribute or another stack's output — not by a {{resolve:ssm:...}} read of a String parameter holding the encoding, which cdkd treats as public and would record in state in the clear. (3) The resource is recorded through the Cloud Control fallback (by a deploy or by 'cdkd import'), which keeps in the clear only the Fn::GetAtt attributes it can vouch for and masks the rest. If the name above is not an Fn::GetAtt attribute CloudFormation accepts for that resource type, no record will ever hold it: stop reading it. If it is one, 'cdkd import' masked it because it could not vouch for the value, or could not read the schema and warned about it when it happened (if that warning named a missing cloudformation:DescribeType permission, grant it first); a deploy that creates or updates the resource records it, unless its value came from a secret. See https://github.com/go-to-k/cdkd/issues/2449. ${DeployEngine.maskedRecordRemedyFor(reads, context.resources, true)}`, resourceType, logicalId);
34911
35700
  }
34912
35701
  function allRecordedSecrets() {
34913
35702
  const all = /* @__PURE__ */ new Map();
@@ -35216,6 +36005,7 @@ async function createFirstThenDeleteOld(input) {
35216
36005
  async function deleteReplacedAfterCreate(logicalId, oldResourceType, currentResource, deleteProvider, deleteProperties, finalSnapshotIdentifier, updateReplacePolicy, secrets, deleteProvisionedBy, noEchoDeleteValues) {
35217
36006
  let deleteResult = void 0;
35218
36007
  let deleteFailed = false;
36008
+ const inlinePolicyClaimed = isStandaloneInlinePolicyType(oldResourceType) ? this.inlinePolicyClaimedFor(oldResourceType, logicalId, this.deployStateResources) : void 0;
35219
36009
  try {
35220
36010
  deleteResult = await deleteProvider.delete(logicalId, currentResource.physicalId, oldResourceType, deleteProperties, {
35221
36011
  expectedRegion: this.stackRegion,
@@ -35224,7 +36014,8 @@ async function deleteReplacedAfterCreate(logicalId, oldResourceType, currentReso
35224
36014
  ...this.replacementDeleteContext(updateReplacePolicy),
35225
36015
  recordedAttributes: currentResource.attributes,
35226
36016
  recordedNoEchoLeaves: currentResource.noEchoLeaves,
35227
- ...noEchoDeleteValues !== void 0 && { noEchoDeleteValues }
36017
+ ...noEchoDeleteValues !== void 0 && { noEchoDeleteValues },
36018
+ ...inlinePolicyClaimed && { inlinePolicyClaimed }
35228
36019
  });
35229
36020
  } catch (deleteError) {
35230
36021
  const deleteMsg = maskSecretsInText(deleteError instanceof Error ? deleteError.message : String(deleteError), secrets);
@@ -38606,10 +39397,7 @@ function noEchoParameterNamesOf(template) {
38606
39397
  const names = /* @__PURE__ */ new Set();
38607
39398
  const declared = template?.Parameters;
38608
39399
  if (declared === null || typeof declared !== "object") return names;
38609
- for (const [name, definition] of Object.entries(declared)) {
38610
- const noEcho = definition?.NoEcho;
38611
- if (noEcho === true || noEcho === "true") names.add(name);
38612
- }
39400
+ for (const [name, definition] of Object.entries(declared)) if (declaresNoEcho(definition)) names.add(name);
38613
39401
  return names;
38614
39402
  }
38615
39403
  function noEchoAttributeNamesOf(record) {
@@ -38846,6 +39634,185 @@ function noEchoComparisonForTemplate(template, knownConditions, values, resource
38846
39634
  return (input) => compare(input);
38847
39635
  }
38848
39636
 
39637
+ //#endregion
39638
+ //#region src/analyzer/security-diff.ts
39639
+ function isSyntheticChange(pc) {
39640
+ return pc.replacementPropagated === true || pc.inPlacePropagated === true || pc.noEchoPromoted === true;
39641
+ }
39642
+ function withChanges(base, changes, side) {
39643
+ const props = { ...base ?? {} };
39644
+ for (const pc of changes) {
39645
+ const value = pc[side];
39646
+ if (value === void 0) delete props[pc.path];
39647
+ else props[pc.path] = value;
39648
+ }
39649
+ return props;
39650
+ }
39651
+ function securityDiffTemplates(changes, records) {
39652
+ const oldResources = {};
39653
+ const newResources = {};
39654
+ const maskedChanges = [];
39655
+ for (const change of changes) {
39656
+ const id = change.logicalId;
39657
+ const record = Object.hasOwn(records, id) ? records[id] : void 0;
39658
+ switch (change.changeType) {
39659
+ case "CREATE":
39660
+ newResources[id] = {
39661
+ Type: change.resourceType,
39662
+ Properties: { ...change.desiredProperties ?? {} }
39663
+ };
39664
+ break;
39665
+ case "DELETE":
39666
+ oldResources[id] = {
39667
+ Type: record?.resourceType ?? change.resourceType,
39668
+ Properties: { ...change.currentProperties ?? record?.properties ?? {} }
39669
+ };
39670
+ break;
39671
+ case "UPDATE": {
39672
+ const pcs = change.propertyChanges ?? [];
39673
+ const typeChange = pcs.find((pc) => pc.path === "Type");
39674
+ const oldType = record?.resourceType ?? change.resourceType;
39675
+ if (typeChange !== void 0 || oldType !== change.resourceType) {
39676
+ oldResources[id] = {
39677
+ Type: typeof typeChange?.oldValue === "string" ? typeChange.oldValue : oldType,
39678
+ Properties: { ...change.currentProperties ?? record?.properties ?? {} }
39679
+ };
39680
+ newResources[id] = {
39681
+ Type: change.resourceType,
39682
+ Properties: { ...change.desiredProperties ?? {} }
39683
+ };
39684
+ break;
39685
+ }
39686
+ for (const pc of pcs) if (pc.maskedExpressionChanged === true && !isSyntheticChange(pc)) maskedChanges.push({
39687
+ logicalId: id,
39688
+ resourceType: change.resourceType,
39689
+ path: pc.path
39690
+ });
39691
+ const real = pcs.filter((pc) => !isSyntheticChange(pc) && pc.maskedExpressionChanged !== true);
39692
+ if (real.length === 0) break;
39693
+ const base = change.currentProperties ?? record?.properties;
39694
+ oldResources[id] = {
39695
+ Type: oldType,
39696
+ Properties: withChanges(base, real, "oldValue")
39697
+ };
39698
+ newResources[id] = {
39699
+ Type: change.resourceType,
39700
+ Properties: withChanges(base, real, "newValue")
39701
+ };
39702
+ break;
39703
+ }
39704
+ }
39705
+ }
39706
+ return {
39707
+ oldTemplate: { Resources: oldResources },
39708
+ newTemplate: { Resources: newResources },
39709
+ maskedChanges
39710
+ };
39711
+ }
39712
+ let cfnDiffModule;
39713
+ function loadCfnDiff() {
39714
+ cfnDiffModule ??= import("@aws-cdk/cloudformation-diff").then((mod) => mod.default ?? mod);
39715
+ return cfnDiffModule;
39716
+ }
39717
+ let cfnDiffUtilModule;
39718
+ function loadCfnDiffUtil() {
39719
+ cfnDiffUtilModule ??= import("@aws-cdk/cloudformation-diff/lib/diff/util.js").then((mod) => mod.default ?? mod);
39720
+ return cfnDiffUtilModule;
39721
+ }
39722
+ function isScrutinized(util, change) {
39723
+ const model = util.loadResourceModel(change.resourceType);
39724
+ const scrutinized = (value) => value !== void 0 && value !== "None";
39725
+ return scrutinized(model?.scrutinizable) || scrutinized(model?.properties?.[change.path]?.scrutinizable);
39726
+ }
39727
+ async function diffSecurity(args) {
39728
+ const templates = securityDiffTemplates(args.changes, args.records);
39729
+ const { oldTemplate, newTemplate } = templates;
39730
+ if (Object.keys(oldTemplate.Resources).length === 0 && Object.keys(newTemplate.Resources).length === 0 && templates.maskedChanges.length === 0) return {
39731
+ broadening: false,
39732
+ rendered: ""
39733
+ };
39734
+ try {
39735
+ const cfnDiff = await loadCfnDiff();
39736
+ const unjudged = templates.maskedChanges.length === 0 ? [] : await loadCfnDiffUtil().then((util) => templates.maskedChanges.filter((c) => isScrutinized(util, c)));
39737
+ const diff = cfnDiff.fullDiff(structuredClone(oldTemplate), structuredClone(newTemplate));
39738
+ const broadening = diff.permissionsBroadened || unjudged.length > 0;
39739
+ const unjudgedNote = unjudged.length === 0 ? "" : "These changed values are masked, so whether they broaden permissions could not be evaluated:\n" + unjudged.map((c) => ` ${c.logicalId} (${c.resourceType}): ${c.path}\n`).join("");
39740
+ if (!diff.permissionsBroadened && !diff.permissionsAnyChanges) return {
39741
+ broadening,
39742
+ rendered: terminalSafe(unjudgedNote)
39743
+ };
39744
+ let table;
39745
+ try {
39746
+ const shown = args.secretMask === void 0 ? void 0 : withholdSecrets(templates, args.secretMask());
39747
+ const shownDiff = shown === void 0 || shown.masked === 0 ? diff : cfnDiff.fullDiff(shown.templates.oldTemplate, shown.templates.newTemplate);
39748
+ table = "";
39749
+ cfnDiff.formatSecurityChanges({ write(chunk) {
39750
+ table += String(chunk);
39751
+ return true;
39752
+ } }, shownDiff, logicalIdToPath(args.records, args.template));
39753
+ if (shown !== void 0 && shown.masked > 0) table += "(Values that hold a secret are shown as ***.)\n";
39754
+ } catch {
39755
+ table = "The security changes are not shown: they could not be checked for secrets.\n";
39756
+ }
39757
+ return {
39758
+ broadening,
39759
+ rendered: terminalSafe(table + unjudgedNote)
39760
+ };
39761
+ } catch (error) {
39762
+ throw new CdkdError(safeMsg`Could not compute the security diff of stack ${args.stackName}, so whether its changes broaden permissions is unknown: ${error instanceof Error ? error.message : String(error)}`, "SECURITY_DIFF_FAILED");
39763
+ }
39764
+ }
39765
+ function holdsSecret(value, mask) {
39766
+ if (typeof value === "string") return mask(value) !== value;
39767
+ if (typeof value === "number" || typeof value === "boolean") return mask(String(value)) !== String(value);
39768
+ if (Array.isArray(value)) return value.some((v) => holdsSecret(v, mask));
39769
+ if (value !== null && typeof value === "object") return Object.entries(value).some(([k, v]) => mask(k) !== k || holdsSecret(v, mask));
39770
+ return false;
39771
+ }
39772
+ function maskLeaves(value, mask, keys = true) {
39773
+ if (Array.isArray(value)) return value.map((v) => maskLeaves(v, mask, keys));
39774
+ if (value !== null && typeof value === "object") {
39775
+ const entries = Object.entries(value).map(([k, v]) => [keys && mask(k) !== k ? "***" : k, maskLeaves(v, mask, keys)]);
39776
+ if (new Set(entries.map(([k]) => k)).size < entries.length) return "***";
39777
+ return Object.fromEntries(entries);
39778
+ }
39779
+ return holdsSecret(value, mask) ? "***" : value;
39780
+ }
39781
+ function withholdSecrets(templates, mask) {
39782
+ const copy = structuredClone(templates);
39783
+ let masked = 0;
39784
+ const ids = /* @__PURE__ */ new Set([...Object.keys(copy.oldTemplate.Resources), ...Object.keys(copy.newTemplate.Resources)]);
39785
+ for (const id of ids) {
39786
+ const oldProps = copy.oldTemplate.Resources[id]?.Properties;
39787
+ const newProps = copy.newTemplate.Resources[id]?.Properties;
39788
+ const keys = /* @__PURE__ */ new Set([...Object.keys(oldProps ?? {}), ...Object.keys(newProps ?? {})]);
39789
+ for (const key of keys) {
39790
+ const oldValue = oldProps?.[key];
39791
+ const newValue = newProps?.[key];
39792
+ const newHolds = holdsSecret(newValue, mask);
39793
+ if (!newHolds && !holdsSecret(oldValue, mask)) continue;
39794
+ masked++;
39795
+ if (newProps !== void 0 && newValue !== void 0) newProps[key] = maskLeaves(newValue, mask);
39796
+ if (oldProps === void 0 || oldValue === void 0) continue;
39797
+ if (newHolds && JSON.stringify(oldValue) !== JSON.stringify(newValue)) oldProps[key] = maskLeaves(oldValue, () => "***", false);
39798
+ else oldProps[key] = maskLeaves(oldValue, mask);
39799
+ }
39800
+ }
39801
+ return {
39802
+ templates: copy,
39803
+ masked
39804
+ };
39805
+ }
39806
+ function logicalIdToPath(records, template) {
39807
+ const map = {};
39808
+ for (const [id, record] of Object.entries(records)) if (typeof record?.constructPath === "string") map[id] = record.constructPath;
39809
+ for (const [id, resource] of Object.entries(template?.Resources ?? {})) {
39810
+ const path = (resource?.Metadata)?.["aws:cdk:path"];
39811
+ if (typeof path === "string") map[id] = path;
39812
+ }
39813
+ return map;
39814
+ }
39815
+
38849
39816
  //#endregion
38850
39817
  //#region src/deployment/resource-deadline.ts
38851
39818
  var InvalidResourceDeadlineError = class extends Error {
@@ -38953,7 +39920,16 @@ async function requireDeploymentApproval(args) {
38953
39920
  const changes = [...args.changes].filter((c) => c.changeType !== "NO_CHANGE" && !isNoEchoPromotionOnly(c));
38954
39921
  const destructiveChanges = findDestructiveChanges(args.stackName, changes, args.records, args.template, new Set(args.recreateTargetIds ?? []));
38955
39922
  const onlyNestedUpdates = changes.every((c) => c.changeType === "UPDATE" && c.resourceType === NESTED_STACK_TYPE$1);
38956
- if (!(level === "destructive" ? destructiveChanges.length > 0 : changes.length > 0 && !onlyNestedUpdates)) return false;
39923
+ const security = level === "broadening" ? await diffSecurity({
39924
+ stackName: args.stackName,
39925
+ changes,
39926
+ records: args.records,
39927
+ template: args.template,
39928
+ secretMask: args.secretMask
39929
+ }).catch((error) => {
39930
+ throw error instanceof Error ? markNonRetryable(error) : error;
39931
+ }) : void 0;
39932
+ if (!(level === "destructive" ? destructiveChanges.length > 0 : level === "broadening" ? security?.broadening === true : changes.length > 0 && !onlyNestedUpdates)) return false;
38957
39933
  const count = (type) => changes.filter((c) => c.changeType === type).length;
38958
39934
  if (enclosingDeadlineExpired()) throw approvalAfterTimeout(args.stackName);
38959
39935
  let approved;
@@ -38966,7 +39942,8 @@ async function requireDeploymentApproval(args) {
38966
39942
  update: count("UPDATE"),
38967
39943
  delete: count("DELETE")
38968
39944
  },
38969
- destructiveChanges
39945
+ destructiveChanges,
39946
+ ...security !== void 0 && { securityChanges: security.rendered }
38970
39947
  }));
38971
39948
  } catch (error) {
38972
39949
  throw error instanceof Error ? markNonRetryable(error) : error;
@@ -38986,7 +39963,7 @@ async function checkDestructivePlan(args) {
38986
39963
  async function approveLateReplacement(args) {
38987
39964
  const level = args.options.requireApproval ?? "never";
38988
39965
  const approve = args.options.approveDeployment;
38989
- if (level === "never" || approve === void 0) return true;
39966
+ if (level === "never" || level === "broadening" || approve === void 0) return true;
38990
39967
  if (enclosingDeadlineExpired()) return false;
38991
39968
  try {
38992
39969
  const approved = await whileEnclosingDeadlinesPaused(() => approve({
@@ -39245,6 +40222,24 @@ async function provisionUpdate(logicalId, change, stateResources, stackName, tem
39245
40222
  if (resourceType === "AWS::CloudFormation::Stack") recordPassedNoEchoParameters(updateSecrets, desiredProps["Parameters"], this.noEchoPositionSources(stateResources));
39246
40223
  if (fingerprintSources !== void 0 && resourceType === "AWS::CloudFormation::Stack") recordPassedParameterClasses(updateSecrets, await classifyPassedParameters(desiredProps["Parameters"], fingerprintSources));
39247
40224
  const desiredForSkipCheck = maskAtCoordinates(redactSecretsForState(markSameGenerationBag({ ...resolvedProps }), updateSecrets, desiredProps), comparisonCoordinates);
40225
+ const legacyDesired = withoutPhysicalNameCopies(updateSecrets, () => maskAtCoordinates(redactSecretsForState(markSameGenerationBag({ ...resolvedProps }), updateSecrets, desiredProps), comparisonCoordinates));
40226
+ const copies = physicalNameCopiesOf.get(updateSecrets);
40227
+ const regionEvidence = getCurrentProducerRegions()?.();
40228
+ const recordOwnSecrets = copies !== void 0 && copies.size > 0 && regionEvidence?.complete === true && recordHoldsEmbeddedReference(currentResource) ? await resolveRecordSecrets({
40229
+ properties: currentResource.properties,
40230
+ attributes: currentResource.attributes
40231
+ }, (token, own) => this.resolver.resolveDynamicReferences(token, persistedTokenResolverContext(own, regionEvidence.regions))) : void 0;
40232
+ const embeddedRewrites = [...embeddedPhysicalNameRewrites(updateSecrets), ...recordOwnSecrets === void 0 || recordOwnSecrets.size === 0 ? [] : embeddedPhysicalNameRewrites(updateSecrets, recordOwnSecrets)];
40233
+ const repairable = [currentProps, currentResource.properties].filter((bag) => bag !== null && typeof bag === "object");
40234
+ for (const bag of new Set(repairable)) for (const key of Object.keys(bag)) {
40235
+ const repaired = repairEmbeddedPhysicalNamesTowards(repairPhysicalNameCopyLeaves(bag[key], legacyDesired[key], desiredForSkipCheck[key]), desiredForSkipCheck[key], embeddedRewrites);
40236
+ if (repaired !== bag[key]) bag[key] = repaired;
40237
+ }
40238
+ const attributes = currentResource.attributes;
40239
+ if (attributes !== void 0 && attributes !== null && embeddedRewrites.length > 0) for (const key of Object.keys(attributes)) {
40240
+ const repaired = replaceEmbeddedPhysicalNameRewrites(attributes[key], embeddedRewrites);
40241
+ if (repaired !== attributes[key]) attributes[key] = repaired;
40242
+ }
39248
40243
  const allowedSilentDrops = this.providerRegistry.getAllowedUnsupportedProperties?.();
39249
40244
  const desiredForSkipCheckAsWritten = currentResource.provisionedBy !== "cc-api" && allowedSilentDrops ? withoutAcceptedSilentDropProperties(resourceType, desiredForSkipCheck, allowedSilentDrops, currentResource.properties) : desiredForSkipCheck;
39250
40245
  const allowedForRecord = allowedSilentDrops ?? /* @__PURE__ */ new Set();
@@ -39666,6 +40661,14 @@ function recordPreviousNoEchoLeaves(registry, stored, desiredLeaves, resolution,
39666
40661
  if (partlyMasked !== leaf && partlyMasked !== "***") recordLogOnlyValue(registry, partlyMasked);
39667
40662
  }
39668
40663
  }
40664
+ function recordHoldsEmbeddedReference(record) {
40665
+ const walk = (node) => {
40666
+ if (typeof node === "string") return node.includes("{{resolve:") && !isSingleDynamicReferenceToken(node);
40667
+ if (node === null || typeof node !== "object") return false;
40668
+ return Object.values(node).some(walk);
40669
+ };
40670
+ return walk(record.properties) || walk(record.attributes);
40671
+ }
39669
40672
 
39670
40673
  //#endregion
39671
40674
  //#region src/deployment/deploy-engine/update-replace.ts
@@ -40699,6 +41702,7 @@ async function executeDeployment(template, currentState, changes, dag, execution
40699
41702
  const concurrency = this.options.concurrency;
40700
41703
  this.deployChanges = changes;
40701
41704
  const newResources = { ...currentState.resources };
41705
+ this.deployStateResources = newResources;
40702
41706
  const actualCounts = {
40703
41707
  created: 0,
40704
41708
  updated: 0,
@@ -42077,7 +43081,7 @@ function conditionFingerprint(template, name, inputOf) {
42077
43081
  inputs[parameter] = { token: input.expression };
42078
43082
  hasToken = true;
42079
43083
  } else {
42080
- if (isPlainObject(definition) && definition["NoEcho"] === true) return void 0;
43084
+ if (declaresNoEcho(definition)) return void 0;
42081
43085
  if (typeof input.value !== "string") return void 0;
42082
43086
  if (carriesDynamicReference(input.value)) return void 0;
42083
43087
  if (coerceParameterTypedValue(input.value, type) !== input.value) return void 0;
@@ -42760,7 +43764,8 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
42760
43764
  changes: changes.values(),
42761
43765
  records: currentState.resources,
42762
43766
  template: effectiveTemplate,
42763
- recreateTargetIds: recreateTargetIdsFor(this.options.recreateTargets, stackName)
43767
+ recreateTargetIds: recreateTargetIdsFor(this.options.recreateTargets, stackName),
43768
+ secretMask: () => this.diffLogMasker(diffResolverContext.recordedSecretValues, effectiveTemplate, parameterValues, currentState.resources)
42764
43769
  })) this.generatedNameGuard?.noteApprovalPrompted();
42765
43770
  this.generatedNameGuard?.recordPlannedIntents();
42766
43771
  this.resolver.resetPhysicalIdFallbackCount();
@@ -43094,6 +44099,7 @@ var DeployEngine = class {
43094
44099
  oldDeletedBeforeCreate = /* @__PURE__ */ new Set();
43095
44100
  healBaseline = {};
43096
44101
  deployChanges = /* @__PURE__ */ new Map();
44102
+ deployStateResources = {};
43097
44103
  stackRecordsView = void 0;
43098
44104
  inlinePolicyWriters = /* @__PURE__ */ new Map();
43099
44105
  attributeHeals = /* @__PURE__ */ new Map();
@@ -43110,7 +44116,9 @@ var DeployEngine = class {
43110
44116
  this.exportIndexStore = exportIndexStore;
43111
44117
  this.resolver = new IntrinsicFunctionResolver(stackRegion, {
43112
44118
  strictGetAtt: options.strictGetAtt ?? false,
43113
- cfnFallback: options.cfnFallback ?? true
44119
+ cfnFallback: options.cfnFallback ?? true,
44120
+ ...options.producerLookup && { producerLookup: options.producerLookup },
44121
+ ...options.consumerAccount && { consumerAccount: options.consumerAccount }
43114
44122
  });
43115
44123
  this.options.concurrency = options.concurrency ?? 10;
43116
44124
  this.options.dryRun = options.dryRun ?? false;
@@ -43158,6 +44166,7 @@ var DeployEngine = class {
43158
44166
  this.oldDeletedBeforeCreate = /* @__PURE__ */ new Set();
43159
44167
  this.healBaseline = {};
43160
44168
  this.deployChanges = /* @__PURE__ */ new Map();
44169
+ this.deployStateResources = {};
43161
44170
  this.inlinePolicyWriters = /* @__PURE__ */ new Map();
43162
44171
  this.attributeHeals = /* @__PURE__ */ new Map();
43163
44172
  this.healedAttributes = /* @__PURE__ */ new Map();
@@ -43227,7 +44236,7 @@ var DeployEngine = class {
43227
44236
  };
43228
44237
  }
43229
44238
  inlinePolicyClaimedFor(resourceType, logicalId, stateResources) {
43230
- if (resourceType !== "AWS::IAM::Policy" && !isInlinePolicyPrincipalType(resourceType)) return;
44239
+ if (resourceType !== "AWS::IAM::Policy" && !isInlinePolicyPrincipalType(resourceType) && !isStandaloneInlinePolicyType(resourceType)) return;
43231
44240
  const args = {
43232
44241
  selfLogicalId: logicalId,
43233
44242
  writers: this.inlinePolicyWriters,
@@ -43374,5 +44383,5 @@ DeployEngine.prototype.replacementNameOrigin = replacementNameOrigin;
43374
44383
  DeployEngine.prototype.orphanedNameCollisionAdvice = orphanedNameCollisionAdvice;
43375
44384
 
43376
44385
  //#endregion
43377
- export { getPriorAttempts as $, isWarmThroughputDecrease as $a, derivePartitionAndUrlSuffix as $c, malformedResourceEntriesWarning as $i, reserveStackCreateToken as $n, isUncertifiedBaselineMaskPosition as $o, AWS_CREDENTIAL_ENV_KEYS as $r, ensureAssetStorage as $s, orphanDeleteNeedsIdentity as $t, noEchoExactEchoLeavesOf as A, repairMalformedOrphansForReadOnly as Aa, getDefaultStateBucketName as Ac, UNREADABLE_RESOURCES_MAP_ROW as Ai, maskEventTextWithBoundBags as An, passedNoEchoParametersOf as Ao, deleteSkipReason as Ar, acceptedCreateOnlyDropsOf as As, isHandledOrphan as At, beginDeleteWait as B, findSilentDropProperties as Ba, stateBucketExistenceConfirmed as Bc, malformedExportNamesWarning as Bi, ccRoutedFinalSnapshotError as Bn, printingCorpusOf as Bo, DiffCalculator as Br, orphansCarriedFrom as Bs, withStackRecords as Bt, recordRetainedForReadoption as C, refuseMalformedResourcePropertiesForExport as Ca, warnFinchArgvExposure as Cc, withSharedDrainBudget as Ci, collectPublishedOutputNames as Cn, maskAtCoordinates as Co, customResourceResponseExpirationWarning as Cr, CrossPrefixReadError as Cs, revertedNestedRowIds as Ct, withResourceDeadline as D, refuseMalformedResourcesForExport as Da, getDockerImageBySourceHash as Dc, STATE_REGION_DIVERGED as Di, DEFAULT_RESOURCE_WARN_AFTER_MS as Dn, noEchoCoordinatesOf as Do, UNSPECIFIED_SKIP_REASON as Dr, isAccessDenied$1 as Ds, withNestedStackContext as Dt, serviceTokenBlockingReason as E, refuseMalformedResourcesForDestroy as Ea, AssetManifestLoader as Ec, JSON_LISTING_HOLE_VALUE as Ei, DEFAULT_RESOURCE_TIMEOUT_MS as En, maskedLeafCoordinatesOf as Eo, unchangedBehindSecretReference as Er, crossPrefixDeniedWarning as Es, getCurrentNestedStackContext as Et, isProtectionValueActive as F, unpreviewableOrphanRecords as Fa, resolveCaptureObservedState as Fc, hasReadableOutputs as Fi, storedSecretNameNeedles as Fn, carryLogOnlyValues as Fo, ec2InstanceProtectionSite as Fr, hasUnverifiableParameterRefusal as Fs, replayFailedOperations as Ft, DELETE_INDEX_WAIT_PROCEED_NOTE as G, findReplacedReadersOfRecreateTargets as Ga, MIGRATE_TMP_PREFIX as Gc, malformedOrphanRecordsRefusalMessage as Gi, unsupportedFinalSnapshotError as Gn, errorCauseChain as Go, producerRegionsFromState as Gr, WorkGraph as Gs, isReplacementOrphan as Gt, deleteBudgetKey as H, withoutSilentDropProperties as Ha, ssmResolvedValueType as Hc, malformedLocalOutputsWarning as Hi, effectiveDeletionPolicy as Hn, recordLogOnlyValue as Ho, IntrinsicFunctionResolver as Hr, AssetPublisher as Hs, recordAfterRollbackUpdate as Ht, perType as I, unreadableOrphanRecords as Ia, resolveSkipPrefix as Ic, hasReadableResources as Ii, extractDeploymentEventError as In, createUnionSecretMasker as Io, isTerminationProtectionPropagationError as Ir, importableOutputKeys as Is, replayRollback as It, waitForIndexesSettled as J, isStatefulRecreateTargetForReplace as Ja, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Jc, malformedOrphansRefusalMessage as Ji, findDestructiveChanges as Jn, markSameGenerationBag as Jo, assertFlagRoleArn as Jr, loadPublishableAssetManifest as Js, recheckFailedPlan as Jt, INDEX_SETTLE_POLL_INTERVAL_MS as K, shownType as Ka, findLargeInlineResources as Kc, malformedOrphanRecordsWarning as Ki, maskingRetryLogger as Kn, maskSecretsInError as Ko, regionLessSecretName as Kr, buildAssetRedirectMap as Ks, planFailedOps as Kt, readProtection as L, unreadableResourceEntries as La, resolveStateBucketWithDefault as Lc, isReadableOrphanRecord as Li, ATOMIC_FINAL_SNAPSHOT_TYPES as Ln, hasMaskableValues as Lo, observeThenDisableInstanceApiTermination as Lr, importableOutputs as Ls, awaitInFlightSibling as Lt, recordedProtectionEvidence as M, repairMalformedResourceEntriesForReadOnly as Ma, loadCdkJson as Mc, deployRefusesOrphanRowsReason as Mi, secretNamePrintingBag as Mn, readsNoEchoSource as Mo, isWaitAbandonedError as Mr, exportNamesCarriedFrom as Ms, loadJournaledOrphans as Mt, recordedProtectionNote as N, repairMalformedResourcePropertiesForReadOnly as Na, resolveApp as Nc, displayLogicalId as Ni, secretNamedRecordNeedles as Nn, valueAtCoordinate as No, markWaitAbandoned as Nr, hasReadableExportSet as Ns, makeForeignHolderScan as Nt, noEchoAttributeNamesOf as O, refuseMalformedState as Oa, Synthesizer as Oc, STATE_RESOURCES_MALFORMED as Oi, completedReplayEntries as On, noEchoLeavesOf as Oo, deleteIndeterminateGuards as Or, isNotImplemented as Os, deleteJournaledOrphans as Ot, PROTECTION_PROPERTY_BY_TYPE as P, repairMalformedResourcesForReadOnly as Pa, resolveAutoAssetStorage as Pc, hasReadableOrphans as Pi, stateSecretNameNeedles as Pn, liveMatchesUnresolvedTokenFrame as Po, disableInstanceApiTermination as Pr, hasReasonlessBaselineRefusal as Ps, sameJournaledOrphans as Pt, isTruthyCfnBoolean as Q, coerceWarmThroughput as Qa, canonicalizeRegion as Qc, malformedRenderedContainersWarning as Qi, ledgerForStack as Qn, dynamicReferenceTokens as Qo, sendableAssumeRoleCommand as Qr, assertAssetBucketRegion as Qs, seedsDeleteFirstGuard as Qt, DynamoDBGlobalTableProvider as R, withheldAccountClause as Ra, resolveStateBucketWithDefaultAndSource as Rc, isReadableResourceEntry as Ri, PRE_DELETE_SNAPSHOT_TYPES as Rn, literalSplitDelimitersOf as Ro, reDisableInstanceApiTermination as Rr, isReadableBag as Rs, destroyStackRecordsView as Rt, keptForReadoption as S, refuseMalformedResourcePropertiesForDrift as Sa, runDockerStreaming as Sc, parseWebACLArn as Si, collectDeclaredOutputNames as Sn, isMarkedCoordinate as So, applyCustomResourceResponseExpiration as Sr, rebuildClientForBucketRegion as Ss, revertNestedChildFromJournal as St, findServiceTokenRefusals as T, refuseMalformedResourcesForDeploy as Ta, stripControlChars as Tc, passedParameterClassesOf as Ti, bindingSkippedOutputs as Tn, maskWholeValue as To, slowCcOperationTimeoutMs as Tr, applyCrossPrefixScan as Ts, collectNestedChildUnaddressed as Tt, resolveDynamoDbDeleteBudgetClock as U, NO_CC_HANDLERS_REASON as Ua, CFN_TEMPLATE_BODY_LIMIT as Uc, malformedLocalResourceEntriesWarning as Ui, isFinalSnapshotError as Un, shareLogOnlyValues as Uo, poisonRenderedSpellingsCollidingIn as Ur, isSensitiveAttributeName as Us, demoteSupersededOrphans as Ut, compensateRemovedDeletionProtection as V, unwrittenCreateOnlyReplacement as Va, warnDeprecatedNoPrefixCliFlag as Vc, malformedExportSourceWarning as Vi, createPreDeleteFinalSnapshot as Vn, recordLogOnlyParameterValue as Vo, INTRINSIC_KEYS as Vr, shouldRetainResource as Vs, removeProtectionTypeList as Vt, resolveDynamoDbDeleteBudgetMs as W, hasNoCloudControlHandlers as Wa, CFN_TEMPLATE_URL_LIMIT as Wc, malformedLocalResourcesWarning as Wi, refusesFinalSnapshot as Wn, createSecretMasker as Wo, classifyReplaySecretRegion as Wr, stringifyValue as Ws, isJournaledOrphan as Wt, S3_AUTO_DELETE_OBJECTS_TAG as X, renderStatefulReason as Xa, expectedOwnerParam as Xc, malformedOutputsRefusalMessage as Xi, RollbackInlinePolicyWriters as Xn, scrubResourceRecord as Xo, explicitRoleArnOrThrow as Xr, AssetModeResolver as Xs, replacementNeverSwapped as Xt, ECR_AUTO_DELETE_IMAGES_TAG as Y, isStatefulRecreateTargetSync as Ya, decodeListingKey as Yc, malformedOrphansWarning as Yi, formatDestructiveChange as Yn, redactSecretsForState as Yo, assertSendableRoleArn as Yr, rewriteTemplateAssetReferences as Ys, recordUnderIdIsNotOwn as Yt, hasCdkAutoDeleteTag as Z, WARM_THROUGHPUT_MEMBERS as Za, PARTITION_TABLE as Zc, malformedOutputsWarning as Zi, earliestDefined as Zn, DYNAMIC_REFERENCE_TOKEN_SCAN as Zo, isIamRoleArn as Zr, BOOTSTRAP_MARKER_PREFIX as Zs, resolveReplacementOldType as Zt, makeCanonicalizePropertiesFn as _, refuseMalformedResourceEntriesForDestroy as _a, isMalformedEnvKey as _c, keepsSecretReferenceToken as _i, carriedExportAliasExposure as _n, lambdaFunctionNameForMask as _o, readsNoEchoDeleteValues as _r, WHOLE_DYNAMIC_REFERENCE_PATTERN as _s, displacedPhysicalIdShown as _t, findNestedTemplateTreeDefect as a, refuseDivergentRecordRegionForDestroy as aa, validateContainerRepoName as ac, s3BucketDomainName as ai, hasPlainPrototype$1 as al, redactedDeleteAddressFields as an, configIntegerRefusal as ao, readTagList as ar, carriesSecretMask as as, gray as at, lookupEachName as b, refuseMalformedResourceEntriesForOrphan as ba, redactedDockerCause as bc, isStalePlaceholderArnAttribute as bi, isWholeDynamicReferenceValue as bn, TemplateParser as bo, withPrintingSecrets as br, isLockInfoExpired as bs, nestedChildStackName as bt, renderNestedTemplateTreeDefect as c, refuseMalformedOrphanRecordsForDestroy as ca, resolveDockerContextDirectory as cc, s3BucketWebsiteUrl as ci, absoluteAssemblyPathEscape as cl, updatePartialReason as cn, replayWarn as co, tagPlanWarning as cr, recordMaskOnlyValuesIn as cs, yellow as ct, conditionInputsFrom as d, refuseMalformedOrphansForOrphan as da, describeDockerFailure as dc, parameterTypeMayLoseSecretIdentity as di, renderAssemblyPathEscape as dl, WITHHELD_NAME_DISPLAY as dn, requireConfigString as do, CC_BROKEN_REASON as dr, recordProvenPublicExpression as ds, reachableDivergentParameters as dt, malformedResourcePropertiesWarning as ea, getBootstrapMarkerKey as ec, applyCallerIdentityCredentials as ei, AssemblyReader as el, findNestedStackTypeChanges as en, toCfnInteger as eo, withCreateTokenLedger as er, pathCrossesDottedKey as es, markRefusedBeforeApplying as et, parentSuppliedValues as f, refuseMalformedOutputs as fa, dockerSpawnEnvWithSensitive as fc, getAccountInfo as fi, resolveAssemblyPath as fl, displayTextOrWithheld as fn, prefetchCreateOnlyPropertyPaths as fo, ProviderRegistry as fr, wholeStringLeavesOf as fs, resourcesNamingDeclaredParameter as ft, mergeNoChangeOutputs as g, refuseMalformedResourceEntriesForDeploy as ga, isDockerClientEnvKey as gc, isNamelessDynamicReferenceError as gi, secretSafeKeyDisplay as gn, canonicalLambdaFunctionName as go, TemplateNoEchoReresolver as gr, TEMPLATE_SOURCED_RULES as gs, displacedOpClause as gt, keptWholeReasonText as h, refuseMalformedResourceEntries as ha, getDockerCmd as hc, carriesFetchableDynamicReference as hi, secretBearingStateKeyWarning as hn, withRetry as ho, wouldReturnToSdkProvider as hr, STATE_SOURCED_READBACK_RULES as hs, NESTED_PENDING_PARENT_REASON as ht, childTemplateLoader as i, previewableOrphanRecords as ia, validateAssetBucketName as ic, s3BucketArn as ii, hasOwnKey as il, isRedactedRecordedValue as in, configBooleanRefusal as io, planTagDiff as ir, recoverMaskedOutput as is, cyan as it, noEchoParameterNamesOf as j, repairMalformedOutputsForReadOnly as ja, getLegacyStateBucketName as jc, accountArgs as ji, orphanRecordsPrintingBag as jn, readbackPathFor as jo, withIndeterminateGuard as jr, describeRegionValueKind as js, journaledOrphanLines as jt, noEchoComparisonForTemplate as k, repairMalformedOrphanRecordsForReadOnly as ka, synthesisStatusMessage as kc, UNREADABLE_ORPHANS_CONTAINER_ROW as ki, journaledOrphanPrintingBag as kn, noEchoOutputsComparison as ko, deleteLeftInPlace as kr, splitImportedOps as ks, dropFailedHint as kt, templateIdentity as l, refuseMalformedOrphans as la, describeDockerCapturedOutput as lc, coerceParameterTypedValue as li, describeFileReadFailure as ll, DeploymentEventsReader as ln, requireConfigArray as lo, definedAttributes as lr, recordNoEchoAttributeValues as ls, computeParameterTaint as lt, isSecretBearingReferenceString as m, refuseMalformedResourceAttributesForOrphan as ma, formatDockerLoginError as mc, carriesDynamicReference as mi, resolveBucketRegion as ml, secretBearing as mn, describeTypeWithThrottleRetry as mo, isCustomResource as mr, STATE_SOURCED_CROSS_GENERATION_RULES as ms, planOrphanAdoption as mt, IMPLICIT_DELETE_DEPENDENCIES as n, malformedScrubResourceEntriesRefusalMessage as na, parseBootstrapMarker as nc, envCredentialsAreAssumedRole as ni, processStackMessages as nl, inheritProducerRegions as nn, coerceCfnBoolean as no, DBPROXY_TAGS_WHAT as nr, inheritNestedStackParameterAssociations as ns, createReadOnlyAttributeHealerFactory as nt, isAbsoluteAssetPath as o, refuseMalformedNestedChildOutputs as oa, buildDenyExternalAccessPolicy as oc, s3BucketDualStackDomainName as oi, nullPrototypeRecord as ol, redactedDeleteAddressSkip as on, configStringRefusal as oo, refuseMalformedDesiredTags as or, provenPublicValue as os, green as ot, readRecordedConditionVerdicts as p, refuseMalformedOutputsForDestroy as pa, finchSecretArgvRefusal as pc, isImpossibleEmptyStoredAttribute as pi, clearBucketRegionCache as pl, exportAliasCollisionScrubWarning as pn, templateResourceTypes as po, ccBrokenReason as pr, STATE_SOURCED_BASELINE_RULES as ps, makeSiblingClaimReader as pt, deleteTableWithIndexBusyRetry as q, MULTI_REGION_RECREATE_BLOCKED_TYPES as qa, uploadCfnTemplate as qc, malformedOrphanRowsKeptWarning as qi, constructPathOf as qn, maskSecretsInText as qo, applyRoleArnIfSet as qr, createAssetRedirectResolver as qs, planRollback as qt, computeImplicitDeleteEdges as r, malformedStateRefusalMessage as ra, readBootstrapMarkerBody as rc, isSettledInstanceState as ri, defineOwnKey as rl, REDACTED_DELETE_ADDRESS_SKIP_REASON as rn, coerceCfnInteger as ro, DBPROXY_TAG_OPTIONS as rr, recordNestedStackParameterExpressions as rs, bold as rt, listNestedTemplateRows as s, refuseMalformedOrphanRecords as sa, buildDockerImage as sc, s3BucketRegionalDomainName as si, ownValue as sl, updatePartialMessage as sn, readConfigString as so, tagMapAsList as sr, recordMaskOnlyValue as ss, red as st, DeployEngine as t, malformedResourcesWarning as ta, isCrossRegionRedirect as tc, callerEnvCredentials as ti, StageLoadError as tl, getCurrentProducerRegions as tn, toFiniteNumber as to, acquireIdempotencyToken as tr, identityKeyFor as ts, formatResourceLine as tt, conditionFingerprint as u, refuseMalformedOrphansForDestroy as ua, describeDockerExecFailure as uc, isUnboundTemplateParameter as ui, displayAssemblyPath as ul, DeploymentEventsStore as un, requireConfigObject as uo, stringifyIfAssigned as ur, recordNoEchoParameterFreshValue as us, namesAnyDeclaredParameter as ut, chunks as v, refuseMalformedResourceEntriesForImport as va, partitionSensitiveEnv as vc, AWS_NO_VALUE as vi, exportNameNoEchoParameters as vn, sameLambdaFunctionAddress as vo, isCustomResourceType as vr, isSingleDynamicReferenceToken as vs, dropSettledNestedJournals as vt, deferredServiceTokenWarning as w, refuseMalformedResourcePropertiesForOrphan as wa, escapeRegExp$3 as wc, parameterInputsFor as wi, isExportAliasCollision as wn, maskReadbackAtCoordinates as wo, CloudControlProvider as wr, CrossPrefixScanCache as ws, withNestedRevertRun as wt, withApiLimit as x, refuseMalformedResourcePropertiesForDestroy as xa, runDockerForeground as xc, refStateLookupFromResource as xi, noEchoParameterValueSeed as xn, canonicalCoordinates as xo, CUSTOM_RESOURCE_RESPONSE_LIFECYCLE_RULE_ID as xr, S3StateBackend as xs, recordDisplacedSkips as xt, isAccessDeniedError as y, refuseMalformedResourceEntriesForImportSave as ya, redactDockerArgvValues as yc, cfnRefValueFromPhysicalId as yi, exportNameSecretExposure as yn, DagBuilder as yo, getCurrentResourceSecrets as yr, LockManager as ys, getNestedRevertRun as yt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as z, findActionableSilentDrops as za, resolveUseCdkBootstrapAssets as zc, malformedDriftResourcePropertiesWarning as zi, buildFinalSnapshotIdentifier as zn, logOnlyValueCount as zo, reEnableInstanceApiTermination as zr, orphansAfterRollback as zs, getStackRecords as zt };
43378
- //# sourceMappingURL=deploy-engine-dvf1UDuo.js.map
44386
+ export { isTruthyCfnBoolean as $, isStatefulRecreateTargetForReplace as $a, CFN_TEMPLATE_URL_LIMIT as $c, malformedOrphansRefusalMessage as $i, ledgerForStack as $n, markSameGenerationBag as $o, assertSendableRoleArn as $r, stringifyValue as $s, seedsDeleteFirstGuard as $t, noEchoComparisonForTemplate as A, refuseMalformedResourcesForDeploy as Aa, runDockerForeground as Ac, declaresNoEcho as Ai, journaledOrphanPrintingBag as An, maskWholeValue as Ao, deleteIndeterminateGuards as Ar, S3StateBackend as As, dropFailedHint as At, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as B, unpreviewableOrphanRecords as Ba, getLegacyStateBucketName as Bc, hasReadableOutputs as Bi, PRE_DELETE_SNAPSHOT_TYPES as Bn, carryLogOnlyValues as Bo, reDisableInstanceApiTermination as Br, describeRegionValueKind as Bs, getStackRecords as Bt, recordRetainedForReadoption as C, refuseMalformedResourceEntriesForImport as Ca, formatDockerLoginError as Cc, cfnRefValueFromPhysicalId as Ci, resolveBucketRegion as Cl, collectDeclaredOutputNames as Cn, sameLambdaFunctionAddress as Co, applyCustomResourceResponseExpiration as Cr, STATE_SOURCED_CROSS_GENERATION_RULES as Cs, revertNestedChildFromJournal as Ct, withResourceDeadline as D, refuseMalformedResourcePropertiesForDrift as Da, partitionSensitiveEnv as Dc, withSharedDrainBudget as Di, DEFAULT_RESOURCE_TIMEOUT_MS as Dn, isMarkedCoordinate as Do, unchangedBehindSecretReference as Dr, isSingleDynamicReferenceToken as Ds, getCurrentNestedStackContext as Dt, serviceTokenBlockingReason as E, refuseMalformedResourcePropertiesForDestroy as Ea, isMalformedEnvKey as Ec, parseWebACLArn as Ei, bindingSkippedOutputs as En, canonicalCoordinates as Eo, slowCcOperationTimeoutMs as Er, WHOLE_DYNAMIC_REFERENCE_PATTERN as Es, collectNestedChildUnaddressed as Et, PROTECTION_PROPERTY_BY_TYPE as F, repairMalformedOrphansForReadOnly as Fa, AssetManifestLoader as Fc, UNREADABLE_RESOURCES_MAP_ROW as Fi, secretNamedRecordNeedles as Fn, passedNoEchoParametersOf as Fo, markWaitAbandoned as Fr, crossPrefixDeniedWarning as Fs, sameJournaledOrphans as Ft, resolveDynamoDbDeleteBudgetMs as G, findSilentDropProperties as Ga, resolveSkipPrefix as Gc, malformedExportNamesWarning as Gi, isFinalSnapshotError as Gn, printingCorpusOf as Go, poisonRenderedSpellingsCollidingIn as Gr, importableOutputKeys as Gs, isJournaledOrphan as Gt, compensateRemovedDeletionProtection as H, unreadableResourceEntries as Ha, resolveApp as Hc, isReadableOrphanRecord as Hi, ccRoutedFinalSnapshotError as Hn, hasMaskableValues as Ho, DiffCalculator as Hr, hasReadableExportSet as Hs, removeProtectionTypeList as Ht, isProtectionValueActive as I, repairMalformedOutputsForReadOnly as Ia, getDockerImageBySourceHash as Ic, accountArgs as Ii, stateSecretNameNeedles as In, readbackPathFor as Io, disableInstanceApiTermination as Ir, isAccessDenied$1 as Is, replayFailedOperations as It, deleteTableWithIndexBusyRetry as J, NO_CC_HANDLERS_REASON as Ja, resolveUseCdkBootstrapAssets as Jc, malformedLocalResourceEntriesWarning as Ji, maskingRetryLogger as Jn, shareLogOnlyValues as Jo, regionLessSecretName as Jr, orphansAfterRollback as Js, planRollback as Jt, DELETE_INDEX_WAIT_PROCEED_NOTE as K, unwrittenCreateOnlyReplacement as Ka, resolveStateBucketWithDefault as Kc, malformedExportSourceWarning as Ki, refusesFinalSnapshot as Kn, recordLogOnlyParameterValue as Ko, classifyReplaySecretRegion as Kr, importableOutputs as Ks, isReplacementOrphan as Kt, perType as L, repairMalformedResourceEntriesForReadOnly as La, Synthesizer as Lc, deployRefusesOrphanRowsReason as Li, storedSecretNameNeedles as Ln, readsNoEchoSource as Lo, ec2InstanceProtectionSite as Lr, isNotImplemented as Ls, replayRollback as Lt, noEchoParameterNamesOf as M, refuseMalformedResourcesForExport as Ma, warnFinchArgvExposure as Mc, STATE_REGION_DIVERGED as Mi, orphanRecordsPrintingBag as Mn, noEchoCoordinatesOf as Mo, deleteSkipReason as Mr, CrossPrefixReadError as Ms, journaledOrphanLines as Mt, recordedProtectionEvidence as N, refuseMalformedState as Na, escapeRegExp$3 as Nc, STATE_RESOURCES_MALFORMED as Ni, secretNamePrintingBag as Nn, noEchoLeavesOf as No, withIndeterminateGuard as Nr, CrossPrefixScanCache as Ns, loadJournaledOrphans as Nt, diffSecurity as O, refuseMalformedResourcePropertiesForExport as Oa, redactDockerArgvValues as Oc, parameterInputsFor as Oi, DEFAULT_RESOURCE_WARN_AFTER_MS as On, maskAtCoordinates as Oo, RollbackInlinePolicyWriters as Or, LockManager as Os, withNestedStackContext as Ot, recordedProtectionNote as P, repairMalformedOrphanRecordsForReadOnly as Pa, stripControlChars as Pc, UNREADABLE_ORPHANS_CONTAINER_ROW as Pi, secretNamePrintingBags as Pn, noEchoOutputsComparison as Po, isWaitAbandonedError as Pr, applyCrossPrefixScan as Ps, makeForeignHolderScan as Pt, hasCdkAutoDeleteTag as Q, MULTI_REGION_RECREATE_BLOCKED_TYPES as Qa, CFN_TEMPLATE_BODY_LIMIT as Qc, malformedOrphanRowsKeptWarning as Qi, earliestDefined as Qn, maskSecretsInText as Qo, assertFlagRoleArn as Qr, isSensitiveAttributeName as Qs, resolveReplacementOldType as Qt, readProtection as R, repairMalformedResourcePropertiesForReadOnly as Ra, synthesisStatusMessage as Rc, displayLogicalId as Ri, extractDeploymentEventError as Rn, valueAtCoordinate as Ro, isTerminationProtectionPropagationError as Rr, splitImportedOps as Rs, awaitInFlightSibling as Rt, keptForReadoption as S, refuseMalformedResourceEntriesForDestroy as Sa, finchSecretArgvRefusal as Sc, AWS_NO_VALUE as Si, clearBucketRegionCache as Sl, noEchoParameterValueSeed as Sn, lambdaFunctionNameForMask as So, CUSTOM_RESOURCE_RESPONSE_LIFECYCLE_RULE_ID as Sr, STATE_SOURCED_BASELINE_RULES as Ss, recordDisplacedSkips as St, findServiceTokenRefusals as T, refuseMalformedResourceEntriesForOrphan as Ta, isDockerClientEnvKey as Tc, refStateLookupFromResource as Ti, isExportAliasCollision as Tn, TemplateParser as To, CloudControlProvider as Tr, TEMPLATE_SOURCED_RULES as Ts, withNestedRevertRun as Tt, deleteBudgetKey as U, withheldAccountClause as Ua, resolveAutoAssetStorage as Uc, isReadableResourceEntry as Ui, createPreDeleteFinalSnapshot as Un, literalSplitDelimitersOf as Uo, INTRINSIC_KEYS as Ur, hasReasonlessBaselineRefusal as Us, recordAfterRollbackUpdate as Ut, beginDeleteWait as V, unreadableOrphanRecords as Va, loadCdkJson as Vc, hasReadableResources as Vi, buildFinalSnapshotIdentifier as Vn, createUnionSecretMasker as Vo, reEnableInstanceApiTermination as Vr, exportNamesCarriedFrom as Vs, withStackRecords as Vt, resolveDynamoDbDeleteBudgetClock as W, findActionableSilentDrops as Wa, resolveCaptureObservedState as Wc, malformedDriftResourcePropertiesWarning as Wi, effectiveDeletionPolicy as Wn, logOnlyValueCount as Wo, IntrinsicFunctionResolver as Wr, hasUnverifiableParameterRefusal as Ws, demoteSupersededOrphans as Wt, ECR_AUTO_DELETE_IMAGES_TAG as X, findReplacedReadersOfRecreateTargets as Xa, warnDeprecatedNoPrefixCliFlag as Xc, malformedOrphanRecordsRefusalMessage as Xi, findDestructiveChanges as Xn, errorCauseChain as Xo, refuseUnreadableCdkCrossAccountRefs as Xr, shouldRetainResource as Xs, recordUnderIdIsNotOwn as Xt, waitForIndexesSettled as Y, hasNoCloudControlHandlers as Ya, stateBucketExistenceConfirmed as Yc, malformedLocalResourcesWarning as Yi, constructPathOf as Yn, createSecretMasker as Yo, producerLookupOver as Yr, orphansCarriedFrom as Ys, recheckFailedPlan as Yt, S3_AUTO_DELETE_OBJECTS_TAG as Z, shownType as Za, ssmResolvedValueType as Zc, malformedOrphanRecordsWarning as Zi, formatDestructiveChange as Zn, maskSecretsInError as Zo, applyRoleArnIfSet as Zr, AssetPublisher as Zs, replacementNeverSwapped as Zt, makeCanonicalizePropertiesFn as _, refuseMalformedOutputs as _a, resolveDockerContextDirectory as _c, isImpossibleEmptyStoredAttribute as _i, absoluteAssemblyPathEscape as _l, secretSafeKeyDisplay as _n, prefetchCreateOnlyPropertyPaths as _o, TemplateNoEchoReresolver as _r, recordMaskOnlyValuesIn as _s, displacedOpClause as _t, findNestedTemplateTreeDefect as a, malformedResourcePropertiesWarning as aa, AssetModeResolver as ac, callerEnvCredentials as ai, expectedOwnerParam as al, isRedactedRecordedValue as an, toCfnInteger as ao, planTagDiff as ar, DYNAMIC_REFERENCE_TOKEN_SCAN as as, cyan as at, lookupEachName as b, refuseMalformedResourceEntries as ba, describeDockerFailure as bc, isNamelessDynamicReferenceError as bi, renderAssemblyPathEscape as bl, exportNameSecretExposure as bn, withRetry as bo, getCurrentResourceSecrets as br, recordProvenPublicExpression as bs, getNestedRevertRun as bt, renderNestedTemplateTreeDefect as c, malformedStateRefusalMessage as ca, ensureAssetStorage as cc, s3BucketArn as ci, derivePartitionAndUrlSuffix as cl, updatePartialMessage as cn, coerceCfnInteger as co, tagMapAsList as cr, pathCrossesDottedKey as cs, red as ct, conditionInputsFrom as d, refuseMalformedNestedChildOutputs as da, parseBootstrapMarker as dc, s3BucketRegionalDomainName as di, processStackMessages as dl, DeploymentEventsStore as dn, configStringRefusal as do, stringifyIfAssigned as dr, recordNestedStackParameterExpressions as ds, namesAnyDeclaredParameter as dt, malformedOrphansWarning as ea, WorkGraph as ec, explicitRoleArnOrThrow as ei, MIGRATE_TMP_PREFIX as el, orphanDeleteNeedsIdentity as en, isStatefulRecreateTargetSync as eo, reserveStackCreateToken as er, redactSecretsForState as es, getPriorAttempts as et, parentSuppliedValues as f, refuseMalformedOrphanRecords as fa, readBootstrapMarkerBody as fc, s3BucketWebsiteUrl as fi, defineOwnKey as fl, WITHHELD_NAME_DISPLAY as fn, readConfigString as fo, CC_BROKEN_REASON as fr, recoverMaskedOutput as fs, reachableDivergentParameters as ft, mergeNoChangeOutputs as g, refuseMalformedOrphansForOrphan as ga, buildDockerImage as gc, getAccountInfo as gi, ownValue as gl, secretBearingStateKeyWarning as gn, requireConfigString as go, wouldReturnToSdkProvider as gr, recordMaskOnlyValue as gs, NESTED_PENDING_PARENT_REASON as gt, keptWholeReasonText as h, refuseMalformedOrphansForDestroy as ha, buildDenyExternalAccessPolicy as hc, parameterTypeMayLoseSecretIdentity as hi, nullPrototypeRecord as hl, secretBearing as hn, requireConfigObject as ho, isCustomResource as hr, provenPublicValue as hs, planOrphanAdoption as ht, childTemplateLoader as i, malformedResourceEntriesWarning as ia, rewriteTemplateAssetReferences as ic, applyCallerIdentityCredentials as ii, decodeListingKey as il, REDACTED_DELETE_ADDRESS_SKIP_REASON as in, isWarmThroughputDecrease as io, DBPROXY_TAG_OPTIONS as ir, recordPhysicalNameCopy as is, bold as it, noEchoExactEchoLeavesOf as j, refuseMalformedResourcesForDestroy as ja, runDockerStreaming as jc, JSON_LISTING_HOLE_VALUE as ji, maskEventTextWithBoundBags as jn, maskedLeafCoordinatesOf as jo, deleteLeftInPlace as jr, rebuildClientForBucketRegion as js, isHandledOrphan as jt, noEchoAttributeNamesOf as k, refuseMalformedResourcePropertiesForOrphan as ka, redactedDockerCause as kc, passedParameterClassesOf as ki, completedReplayEntries as kn, maskReadbackAtCoordinates as ko, UNSPECIFIED_SKIP_REASON as kr, isLockInfoExpired as ks, deleteJournaledOrphans as kt, templateIdentity as l, previewableOrphanRecords as la, getBootstrapMarkerKey as lc, s3BucketDomainName as li, AssemblyReader as ll, updatePartialReason as ln, configBooleanRefusal as lo, tagPlanWarning as lr, identityKeyFor as ls, yellow as lt, isSecretBearingReferenceString as m, refuseMalformedOrphans as ma, validateContainerRepoName as mc, isUnboundTemplateParameter as mi, hasPlainPrototype$1 as ml, exportAliasCollisionScrubWarning as mn, requireConfigArray as mo, ccBrokenReason as mr, carriesSecretMask as ms, makeSiblingClaimReader as mt, IMPLICIT_DELETE_DEPENDENCIES as n, malformedOutputsWarning as na, createAssetRedirectResolver as nc, sendableAssumeRoleCommand as ni, uploadCfnTemplate as nl, getCurrentProducerRegions as nn, WARM_THROUGHPUT_MEMBERS as no, acquireIdempotencyToken as nr, withPhysicalNameCopies as ns, formatResourceLine as nt, isAbsoluteAssetPath as o, malformedResourcesWarning as oa, BOOTSTRAP_MARKER_PREFIX as oc, envCredentialsAreAssumedRole as oi, PARTITION_TABLE as ol, redactedDeleteAddressFields as on, toFiniteNumber as oo, readTagList as or, dynamicReferenceTokens as os, gray as ot, readRecordedConditionVerdicts as p, refuseMalformedOrphanRecordsForDestroy as pa, validateAssetBucketName as pc, coerceParameterTypedValue as pi, hasOwnKey as pl, displayTextOrWithheld as pn, replayWarn as po, ProviderRegistry as pr, splitGetAttStringForm as ps, resourcesNamingDeclaredParameter as pt, INDEX_SETTLE_POLL_INTERVAL_MS as q, withoutSilentDropProperties as qa, resolveStateBucketWithDefaultAndSource as qc, malformedLocalOutputsWarning as qi, unsupportedFinalSnapshotError as qn, recordLogOnlyValue as qo, producerRegionsFromState as qr, isReadableBag as qs, planFailedOps as qt, computeImplicitDeleteEdges as r, malformedRenderedContainersWarning as ra, loadPublishableAssetManifest as rc, AWS_CREDENTIAL_ENV_KEYS as ri, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as rl, inheritProducerRegions as rn, coerceWarmThroughput as ro, DBPROXY_TAGS_WHAT as rr, withoutPhysicalNameCopies as rs, createReadOnlyAttributeHealerFactory as rt, listNestedTemplateRows as s, malformedScrubResourceEntriesRefusalMessage as sa, assertAssetBucketRegion as sc, isSettledInstanceState as si, canonicalizeRegion as sl, redactedDeleteAddressSkip as sn, coerceCfnBoolean as so, refuseMalformedDesiredTags as sr, isUncertifiedBaselineMaskPosition as ss, green as st, DeployEngine as t, malformedOutputsRefusalMessage as ta, buildAssetRedirectMap as tc, isIamRoleArn as ti, findLargeInlineResources as tl, findNestedStackTypeChanges as tn, renderStatefulReason as to, withCreateTokenLedger as tr, scrubResourceRecord as ts, markRefusedBeforeApplying as tt, conditionFingerprint as u, refuseDivergentRecordRegionForDestroy as ua, isCrossRegionRedirect as uc, s3BucketDualStackDomainName as ui, StageLoadError as ul, DeploymentEventsReader as un, configIntegerRefusal as uo, definedAttributes as ur, inheritNestedStackParameterAssociations as us, computeParameterTaint as ut, chunks as v, refuseMalformedOutputsForDestroy as va, describeDockerCapturedOutput as vc, carriesDynamicReference as vi, describeFileReadFailure as vl, carriedExportAliasExposure as vn, templateResourceTypes as vo, readsNoEchoDeleteValues as vr, recordNoEchoAttributeValues as vs, displacedPhysicalIdShown as vt, deferredServiceTokenWarning as w, refuseMalformedResourceEntriesForImportSave as wa, getDockerCmd as wc, isStalePlaceholderArnAttribute as wi, collectPublishedOutputNames as wn, DagBuilder as wo, customResourceResponseExpirationWarning as wr, STATE_SOURCED_READBACK_RULES as ws, revertedNestedRowIds as wt, withApiLimit as x, refuseMalformedResourceEntriesForDeploy as xa, dockerSpawnEnvWithSensitive as xc, keepsSecretReferenceToken as xi, resolveAssemblyPath as xl, isWholeDynamicReferenceValue as xn, canonicalLambdaFunctionName as xo, withPrintingSecrets as xr, wholeStringLeavesOf as xs, nestedChildStackName as xt, isAccessDeniedError as y, refuseMalformedResourceAttributesForOrphan as ya, describeDockerExecFailure as yc, carriesFetchableDynamicReference as yi, displayAssemblyPath as yl, exportNameNoEchoParameters as yn, describeTypeWithThrottleRetry as yo, isCustomResourceType as yr, recordNoEchoParameterFreshValue as ys, dropSettledNestedJournals as yt, DynamoDBGlobalTableProvider as z, repairMalformedResourcesForReadOnly as za, getDefaultStateBucketName as zc, hasReadableOrphans as zi, ATOMIC_FINAL_SNAPSHOT_TYPES as zn, liveMatchesUnresolvedTokenFrame as zo, observeThenDisableInstanceApiTermination as zr, acceptedCreateOnlyDropsOf as zs, destroyStackRecordsView as zt };
44387
+ //# sourceMappingURL=deploy-engine-CJTG3tft.js.map