@go-to-k/cdkd 0.290.5 → 0.290.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as isVersionOnlyInvocation, t as getCdkdVersion } from "./version-BBIkp8ja.js";
2
+ import { n as isVersionOnlyInvocation, t as getCdkdVersion } from "./version-XcHj8rQZ.js";
3
3
 
4
4
  //#region src/cli/pipe-close-handler.ts
5
5
  /**
@@ -74,7 +74,7 @@ async function main() {
74
74
  console.log(getCdkdVersion());
75
75
  return;
76
76
  }
77
- const { buildProgram } = await import("./program-D30EPjOn.js");
77
+ const { buildProgram } = await import("./program-Ckl60p0E.js");
78
78
  const program = buildProgram();
79
79
  const args = reorderArgs(process.argv);
80
80
  await program.parseAsync(args);
@@ -1,6 +1,6 @@
1
1
  import { b as displayIdent, d as applyDefaultNameForFallback, f as explicitNamePropertyFor, g as looksLikeCdkdGeneratedName, h as getCurrentStackName, m as generateResourceNameWithFallback, n as getLogger, p as generateResourceName, r as isStdoutReservedForPayload, s as getLiveRenderer, v as withStackName, x as displaySafe, y as UNRENDERABLE } from "./logger-th1myfgh.js";
2
2
  import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
3
- import { t as getCdkdVersion } from "./version-BBIkp8ja.js";
3
+ import { t as getCdkdVersion } from "./version-XcHj8rQZ.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { createHash, randomUUID } from "node:crypto";
6
6
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -7218,6 +7218,94 @@ function describeDockerFailure(error, args) {
7218
7218
  return redactDockerArgvInText(capturedStreamText(error, "stderr") || thrownMessageText(error) || safeStringify(error), args);
7219
7219
  }
7220
7220
  /**
7221
+ * A `cause` that is safe to CHAIN onto a wrapper error, for a caller that
7222
+ * wants the retry classifiers to see the failure as an object rather than as
7223
+ * an interpolated string (issue go-to-k/cdkd#2075).
7224
+ *
7225
+ * Attaching the raw `execFile` error reopens the channel go-to-k/cdkd#2440
7226
+ * closed. The mandate above applies to every docker failure text this module
7227
+ * hands out, "including one whose argv carries no user data today" — and a
7228
+ * chained cause IS such a text: `formatError` prints `cause.message`, and the
7229
+ * CLI's top-level handler walks the whole chain. The raw message is the
7230
+ * command line, so the moment an argv gains a `-e` or a `--build-arg` the
7231
+ * secret is in a printed line again, from a call site nobody re-reads.
7232
+ *
7233
+ * So the returned cause carries the REDACTED description as its message, and
7234
+ * chains nothing further. What the classifiers read is copied across — but
7235
+ * through an ALLOWLIST ({@link CLASSIFICATION_FIELDS}), never by sweeping the
7236
+ * original's own keys.
7237
+ *
7238
+ * The allowlist is the whole point, and a denylist was the first cut: it
7239
+ * skipped `message` / `stack` / `cause` and copied the rest, which carried
7240
+ * `err.cmd` — the full command line — onto the new error verbatim. That is
7241
+ * the SAME field that defeated four rounds of the go-to-k/cdkd#2440 fence
7242
+ * (`.claude/rules/docker-argv-redaction.md`), reintroduced inside the function
7243
+ * written to close it. `stderr` / `stdout` are excluded for the same reason:
7244
+ * the composer above has already read and REDACTED them into the message, so
7245
+ * copying the raw streams would hand back exactly what it removed.
7246
+ *
7247
+ * Fail-closed is the correct direction here for the reason the cache-param
7248
+ * allowlist gives: a field missing from the allowlist costs one degraded retry
7249
+ * classification, while a field missing from a denylist costs a printed
7250
+ * credential.
7251
+ */
7252
+ /**
7253
+ * The fields {@link redactedDockerCause} carries from the original error onto
7254
+ * the redacted one.
7255
+ *
7256
+ * WHAT EACH HALF IS FOR, stated precisely because an earlier revision of this
7257
+ * comment got it wrong in a way that reads as more than it is. The AWS-shaped
7258
+ * entries (`$metadata`, `$fault`, `__type`, `code`, `statusCode`) are what
7259
+ * `isThrottlingError` / `isTransientServerError` /
7260
+ * `describeRetryClassificationSignals` actually consult, and they are reachable
7261
+ * here only when an SDK error is the cause -- the ECR-login path, whose
7262
+ * `GetAuthorizationToken` failure can be one.
7263
+ *
7264
+ * `exitCode` is NOT read by any classifier. It is carried because it is the
7265
+ * ONLY field the DOMINANT failure has: these four sites reject through
7266
+ * `spawnStreaming`, whose `SpawnError` sets `stderr` / `stdout` / `exitCode`
7267
+ * and nothing else, so without it a non-zero docker exit produced a cause with
7268
+ * a name and a message and no other content at all. What that buys is the
7269
+ * DIAGNOSTIC -- `cli/index.ts` renders the chain's own enumerable props -- not
7270
+ * a retry decision. Do not restate it as a classification field.
7271
+ *
7272
+ * `stderr` / `stdout` stay OFF: the composer has already read and REDACTED
7273
+ * them into the message, so copying the raw streams would hand back exactly
7274
+ * what it removed.
7275
+ */
7276
+ const CLASSIFICATION_FIELDS = [
7277
+ "exitCode",
7278
+ "code",
7279
+ "errno",
7280
+ "signal",
7281
+ "status",
7282
+ "statusCode",
7283
+ "$metadata",
7284
+ "$fault",
7285
+ "__type"
7286
+ ];
7287
+ function redactedDockerCause(error, args) {
7288
+ if (!(error instanceof Error)) return void 0;
7289
+ const cause = new Error(describeDockerFailure(error, args));
7290
+ try {
7291
+ cause.name = error.name;
7292
+ } catch {}
7293
+ const NON_RETRYABLE_MARKER = Symbol.for("cdkd.nonRetryable");
7294
+ try {
7295
+ if (error[NON_RETRYABLE_MARKER] === true) Object.defineProperty(cause, NON_RETRYABLE_MARKER, {
7296
+ value: true,
7297
+ enumerable: false,
7298
+ configurable: true
7299
+ });
7300
+ } catch {}
7301
+ const source = error;
7302
+ const target = cause;
7303
+ for (const key of CLASSIFICATION_FIELDS) try {
7304
+ if (key in source) target[key] = source[key];
7305
+ } catch {}
7306
+ return cause;
7307
+ }
7308
+ /**
7221
7309
  * Composer for a captured-output failure where the diagnostic may be on
7222
7310
  * STDOUT rather than stderr (`runDockerStreaming`'s non-zero-exit path, whose
7223
7311
  * `SpawnError` carries both). `fallback` is used when neither stream said
@@ -7474,7 +7562,12 @@ var DockerAssetPublisher = class {
7474
7562
  try {
7475
7563
  await this.tagImage(actualTag, tag);
7476
7564
  } catch (err) {
7477
- throw new AssetError(`Docker tag failed re-tagging '${actualTag}' → '${tag}': ${err.message ?? String(err)}`);
7565
+ const e = err;
7566
+ throw new AssetError(`Docker tag failed re-tagging '${actualTag}' → '${tag}': ${e.message ?? String(err)}`, e.cause instanceof Error ? e.cause : redactedDockerCause(err, [
7567
+ "tag",
7568
+ actualTag,
7569
+ tag
7570
+ ]));
7478
7571
  }
7479
7572
  }
7480
7573
  }
@@ -7549,7 +7642,7 @@ var DockerAssetPublisher = class {
7549
7642
  await runDockerStreaming(loginArgs, { input: password });
7550
7643
  loggedInRegistries.add(registryKey);
7551
7644
  } catch (err) {
7552
- throw new AssetError(`ECR login failed: ${formatDockerLoginError(describeDockerFailure(err, loginArgs), endpoint)}`);
7645
+ throw new AssetError(`ECR login failed: ${formatDockerLoginError(describeDockerFailure(err, loginArgs), endpoint)}`, redactedDockerCause(err, loginArgs));
7553
7646
  }
7554
7647
  }
7555
7648
  /**
@@ -7564,7 +7657,7 @@ var DockerAssetPublisher = class {
7564
7657
  try {
7565
7658
  await runDockerStreaming(tagArgs);
7566
7659
  } catch (err) {
7567
- throw new AssetError(`Docker tag failed: ${describeDockerFailure(err, tagArgs)}`);
7660
+ throw new AssetError(`Docker tag failed: ${describeDockerFailure(err, tagArgs)}`, redactedDockerCause(err, tagArgs));
7568
7661
  }
7569
7662
  }
7570
7663
  /**
@@ -7578,7 +7671,7 @@ var DockerAssetPublisher = class {
7578
7671
  try {
7579
7672
  await runDockerStreaming(pushArgs);
7580
7673
  } catch (err) {
7581
- throw new AssetError(`Docker push failed: ${describeDockerFailure(err, pushArgs)}`);
7674
+ throw new AssetError(`Docker push failed: ${describeDockerFailure(err, pushArgs)}`, redactedDockerCause(err, pushArgs));
7582
7675
  }
7583
7676
  }
7584
7677
  /**
@@ -9679,7 +9772,7 @@ var S3StateBackend = class {
9679
9772
  }));
9680
9773
  } catch (error) {
9681
9774
  const name = error.name;
9682
- if (name === "NotFound" || name === "NoSuchBucket") throw new StateError(`State bucket '${this.config.bucket}' does not exist. Run 'cdkd bootstrap' to create it, or specify an existing bucket via --state-bucket, CDKD_STATE_BUCKET, or cdk.json context.cdkd.stateBucket.`);
9775
+ if (name === "NotFound" || name === "NoSuchBucket") throw new StateError(`State bucket '${this.config.bucket}' does not exist. Run 'cdkd bootstrap' to create it, or specify an existing bucket via --state-bucket, CDKD_STATE_BUCKET, or cdk.json context.cdkd.stateBucket.`, error instanceof Error ? error : void 0);
9683
9776
  const normalized = normalizeAwsError(error, {
9684
9777
  bucket: this.config.bucket,
9685
9778
  operation: "HeadBucket"
@@ -9811,7 +9904,7 @@ var S3StateBackend = class {
9811
9904
  }
9812
9905
  return response.ETag;
9813
9906
  } catch (error) {
9814
- if (error.name === "PreconditionFailed") throw new StateError(`State has been modified by another process. Expected ETag: ${expectedEtag}, but state has changed.`);
9907
+ if (error.name === "PreconditionFailed") throw new StateError(`State has been modified by another process. Expected ETag: ${expectedEtag}, but state has changed.`, error instanceof Error ? error : void 0);
9815
9908
  const normalized = normalizeAwsError(error, {
9816
9909
  bucket: this.config.bucket,
9817
9910
  operation: "PutObject"
@@ -18099,6 +18192,7 @@ const PROPERTY_COVERAGE_BY_TYPE = /* @__PURE__ */ new Map([
18099
18192
  ["MultiRegionConsistency", "not yet implemented by cdkd"],
18100
18193
  ["ReadOnDemandThroughputSettings", "not yet implemented by cdkd"],
18101
18194
  ["ReadProvisionedThroughputSettings", "not yet implemented by cdkd"],
18195
+ ["VectorIndexes", "not yet implemented by cdkd"],
18102
18196
  ["WarmThroughput", "not yet implemented by cdkd"]
18103
18197
  ]),
18104
18198
  createOnlyDrops: /* @__PURE__ */ new Set()
@@ -18125,7 +18219,7 @@ const PROPERTY_COVERAGE_BY_TYPE = /* @__PURE__ */ new Map([
18125
18219
  "TimeToLiveSpecification",
18126
18220
  "WarmThroughput"
18127
18221
  ]),
18128
- silentDrop: /* @__PURE__ */ new Map([["ImportSourceSpecification", "S3 import uses the separate ImportTable API (not CreateTable) and is create-only with no readback; deferred to a dedicated import-from-S3 PR"]]),
18222
+ silentDrop: /* @__PURE__ */ new Map([["ImportSourceSpecification", "S3 import uses the separate ImportTable API (not CreateTable) and is create-only with no readback; deferred to a dedicated import-from-S3 PR"], ["VectorIndexes", "not yet implemented by cdkd"]]),
18129
18223
  createOnlyDrops: /* @__PURE__ */ new Set(["ImportSourceSpecification"])
18130
18224
  }],
18131
18225
  ["AWS::EC2::EIP", {
@@ -23363,15 +23457,19 @@ function withoutProducerRegions(context) {
23363
23457
  }
23364
23458
  /**
23365
23459
  * Masked log twins registered this pass, per pass bag (issue #3100;
23366
- * `rememberLogTwin` / `logTwinOfProduct`). Log-only: nothing that resolves or
23367
- * persists a value reads it.
23460
+ * `rememberLogTwin` / `logTwinOfProduct`). Nothing that RESOLVES a value reads
23461
+ * it. One persistence decision does: `resolveBase64` registers its encoding
23462
+ * mask-only when the input's position mask fires (issue #3119), which a nested
23463
+ * child also reaches through the inherited-bag lookup (issue #3114).
23368
23464
  *
23369
23465
  * MODULE scope, not instance scope: a region-pinned sibling resolver
23370
23466
  * (`resolverForProducerRegion`) resolves on behalf of the consumer with the
23371
23467
  * consumer's bag, so an instance-local registry left the sibling's twin where
23372
23468
  * the consumer's `Fn::Join` / `Fn::Sub` never looked. The key is still the
23373
- * pass's own bag object, so scope does not widen: another pass holds another
23374
- * bag and cannot reach these entries, and they die with the bag.
23469
+ * pass's own bag object, so scope does not widen to unrelated passes: a pass
23470
+ * reaches only the entries under its own bag and under the bag it was handed
23471
+ * as `inheritedSecrets` (a nested-stack child reading its parent's, issue
23472
+ * #3114), and the entries die with the bag.
23375
23473
  */
23376
23474
  const LOG_TWINS_BY_PASS = /* @__PURE__ */ new WeakMap();
23377
23475
  /**
@@ -24723,6 +24821,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
24723
24821
  async resolveParameters(template, userParameters, options) {
24724
24822
  const inheritedSecrets = options?.inheritedSecrets;
24725
24823
  const maskInherited = (text) => inheritedSecrets && inheritedSecrets.size > 0 ? maskSecretsInText(text, inheritedSecrets) : text;
24824
+ const inheritedLogContext = {
24825
+ template,
24826
+ resources: {},
24827
+ ...inheritedSecrets && { inheritedSecrets }
24828
+ };
24726
24829
  const parameters = Object.create(null);
24727
24830
  const templateParameters = template.Parameters;
24728
24831
  if (!templateParameters || typeof templateParameters !== "object") return parameters;
@@ -24735,7 +24838,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
24735
24838
  if (userValue !== void 0) {
24736
24839
  this.refuseCoercedInheritedSecret(name, paramDef, userValue, inheritedSecrets);
24737
24840
  parameters[name] = this.coerceParameterValue(userValue, paramDef.Type);
24738
- this.logger.debug(`Parameter ${name}: using user-provided value ${maskInherited(stringifyParameterForLog(paramDef, userValue))}`);
24841
+ this.logger.debug(`Parameter ${name}: using user-provided value ${maskInherited(stringifyParameterForLog(paramDef, this.maskValueLeaves(userValue, inheritedLogContext)))}`);
24739
24842
  continue;
24740
24843
  }
24741
24844
  }
@@ -25064,7 +25167,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
25064
25167
  const value = context.parameters[logicalId];
25065
25168
  const declared = context.template.Parameters;
25066
25169
  const paramDef = declared != null && Object.hasOwn(declared, logicalId) ? declared[logicalId] : void 0;
25067
- this.logger.debug(`Resolved Ref to parameter: ${logicalId} -> ${this.maskSecretsForLog(stringifyParameterForLog(paramDef, value), context)}`);
25170
+ this.logger.debug(`Resolved Ref to parameter: ${logicalId} -> ${this.maskSecretsForLog(stringifyParameterForLog(paramDef, this.maskValueLeaves(value, context)), context)}`);
25068
25171
  this.recordInheritedParameterSecrets(logicalId, value, context);
25069
25172
  return value;
25070
25173
  }
@@ -25237,10 +25340,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
25237
25340
  this.rejectPlaceholderArnAttribute(resource, attributeName, flatValue, logicalId, context);
25238
25341
  if (resource.resourceType === "AWS::Route53::HostedZone" && attributeName === "NameServers" && typeof flatValue === "string") {
25239
25342
  const nameServers = flatValue === "" ? [] : flatValue.split(",");
25240
- this.logger.debug(`Normalized legacy Fn::GetAtt attribute: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, nameServers), context)}`);
25343
+ this.logger.debug(`Normalized legacy Fn::GetAtt attribute: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, this.maskValueLeaves(nameServers, context)), context)}`);
25241
25344
  return this.noteAttributeSecrecy(logicalId, attributeName, nameServers, context);
25242
25345
  }
25243
- this.logger.debug(`Resolved Fn::GetAtt from attributes: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, flatValue), context)}`);
25346
+ this.logger.debug(`Resolved Fn::GetAtt from attributes: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, this.maskValueLeaves(flatValue, context)), context)}`);
25244
25347
  if (resource.resourceType === NESTED_STACK_RESOURCE_TYPE$1 && attributeName.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX) && carriesDynamicReference(flatValue)) return await this.reresolveCrossStackValue(flatValue, nestedStackChildRegionFromLocalArn(resource.physicalId), context, `nested stack ${logicalId} ${attributeName}`, crossStackSourceKey({ "Fn::GetAtt": getAtt }));
25245
25348
  return this.noteAttributeSecrecy(logicalId, attributeName, flatValue, context);
25246
25349
  }
@@ -25253,7 +25356,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
25253
25356
  break;
25254
25357
  }
25255
25358
  if (cursor !== void 0) {
25256
- this.logger.debug(`Resolved Fn::GetAtt from nested attributes: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, cursor), context)}`);
25359
+ this.logger.debug(`Resolved Fn::GetAtt from nested attributes: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, this.maskValueLeaves(cursor, context)), context)}`);
25257
25360
  return this.noteAttributeSecrecy(logicalId, attributeName, cursor, context);
25258
25361
  }
25259
25362
  }
@@ -25263,7 +25366,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
25263
25366
  throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.maskSecretsForLog(attributeName, context)}]: the nested stack '${logicalId}' declares no output named '${this.maskSecretsForLog(attributeName.slice(8), context)}'. Its outputs are ${declared.length > 0 ? declared.join(", ") : "(none)"}. Check the output name in the nested stack's template, and deploy the child stack again if you have just added it.`));
25264
25367
  }
25265
25368
  const value = await this.constructGuardedAttribute(resource, attributeName, context, logicalId);
25266
- this.logger.debug(`Resolved Fn::GetAtt: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, value), context)}`);
25369
+ this.logger.debug(`Resolved Fn::GetAtt: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, this.maskValueLeaves(value, context)), context)}`);
25267
25370
  return value;
25268
25371
  }
25269
25372
  /**
@@ -25955,7 +26058,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
25955
26058
  const literalList = Array.isArray(rawValues);
25956
26059
  const parts = (await allSettledKeepingFirstRejection(values.map(async (v) => {
25957
26060
  if (typeof v === "string") return {
25958
- ...v.includes("{{resolve:") ? await this.resolveDynamicReferencesWithLogTwin(v, v, context) : {
26061
+ ...v.includes("{{resolve:") ? await this.resolveDynamicReferencesWithLogTwin(v, this.logTwinOfProduct({
26062
+ result: v,
26063
+ twin: v
26064
+ }, context).twin, context) : {
25959
26065
  result: v,
25960
26066
  twin: v
25961
26067
  },
@@ -27277,8 +27383,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27277
27383
  * pass is masked too: the over-masking direction `logTwinOfProduct` accepts.
27278
27384
  */
27279
27385
  splitLogTwins(value, delimiter, pieces, context) {
27280
- const bag = this.logTwinBag(context);
27281
- const sourceTwin = this.isRecordedSecretForLog(value, context) ? "***" : bag ? LOG_TWINS_BY_PASS.get(bag)?.get(value) : void 0;
27386
+ const sourceTwin = this.isRecordedSecretForLog(value, context) ? "***" : this.registeredLogTwin(value, context);
27282
27387
  if (sourceTwin === void 0) return pieces;
27283
27388
  const twinPieces = sourceTwin.split(delimiter);
27284
27389
  const aligned = twinPieces.length === pieces.length && !"***".includes(delimiter);
@@ -27332,6 +27437,48 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27332
27437
  return context?.recordedSecretValues ?? context?.inheritedSecrets;
27333
27438
  }
27334
27439
  /**
27440
+ * The masked twin registered for `value`, looked up under the pass's OWN bag
27441
+ * and under the INHERITED one (issue
27442
+ * [#3114](https://github.com/go-to-k/cdkd/issues/3114)). A nested-stack
27443
+ * child receives, as `inheritedSecrets`, the very object its parent resolved
27444
+ * the `AWS::CloudFormation::Stack` resource with: the deploy engine binds the
27445
+ * resource context's `recordedSecretValues` as the resource's secrets, and
27446
+ * `NestedStackProvider` hands that binding to the child. So a parameter value
27447
+ * the parent built around a short secret (`port:q7` -> `port:***`) is
27448
+ * registered under the child's inherited bag, while the child registers its
27449
+ * own writes under its own bag. Two DIFFERENT registered twins mask the
27450
+ * whole string, the rule `rememberLogTwin` applies within one bag. Lookups
27451
+ * only: `rememberLogTwin` still registers under `logTwinBag`, the context's
27452
+ * own `recordedSecretValues` whenever it carries one (every context
27453
+ * `buildResolverContext` returns does; the log-only context
27454
+ * `resolveParameters` builds carries none, and nothing on that path
27455
+ * registers), so such a child never writes into its parent's registry. A
27456
+ * context with ONLY an inherited bag registers into that bag, as it did
27457
+ * before this lookup existed.
27458
+ *
27459
+ * ONE LEVEL ONLY. The bag a child hands its own nested stack is the child's
27460
+ * OWN resource bag, so no twin registered ABOVE the child is reachable from a
27461
+ * grandchild. Where the middle stack passes the value THROUGH
27462
+ * (`{ Ref: Param }` straight into the grandchild's `Parameters`) nothing ever
27463
+ * registers a twin in that bag, so the grandchild prints the value whether or
27464
+ * not the bag holds pairs. Where the middle RE-WRAPS it (an `Fn::Join` around
27465
+ * the `Ref`) the middle registers its own twin, and the hand-off still drops
27466
+ * a bag holding no pairs (it passes `inheritedSecrets` only when `size` is
27467
+ * nonzero). Both are issue #3156.
27468
+ *
27469
+ * The registry is keyed by VALUE, and `splitLogTwins`' unaligned arm
27470
+ * registers every piece, public ones included. So a child `Fn::Base64` over a
27471
+ * string exactly equal to such a piece of its parent's persists `***` for a
27472
+ * non-secret property, the over-masking hazard issue #3119 already accepts
27473
+ * within one pass, now reachable across the parent / child boundary.
27474
+ */
27475
+ registeredLogTwin(value, context) {
27476
+ const own = context?.recordedSecretValues ? LOG_TWINS_BY_PASS.get(context.recordedSecretValues)?.get(value) : void 0;
27477
+ const inherited = context?.inheritedSecrets ? LOG_TWINS_BY_PASS.get(context.inheritedSecrets)?.get(value) : void 0;
27478
+ if (own === void 0) return inherited;
27479
+ return inherited === void 0 || inherited === own ? own : "***";
27480
+ }
27481
+ /**
27335
27482
  * The log twin of a RESOLUTION PRODUCT — an intrinsic part, variable or
27336
27483
  * placeholder — for issue #3100. Masked whole when its value is a recorded
27337
27484
  * secret. Otherwise a part that carries no mask of its own takes the masked
@@ -27359,8 +27506,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27359
27506
  result: part.result,
27360
27507
  twin: "***"
27361
27508
  };
27362
- const bag = this.logTwinBag(context);
27363
- const registered = bag ? LOG_TWINS_BY_PASS.get(bag)?.get(part.result) : void 0;
27509
+ const registered = this.registeredLogTwin(part.result, context);
27364
27510
  if (registered === void 0 || registered === part.twin) return part;
27365
27511
  return {
27366
27512
  result: part.result,
@@ -27374,7 +27520,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27374
27520
  * two DIFFERENT masked twins for one string register `***` for the whole
27375
27521
  * string, since their spans cannot be merged. Scoped to the pass's bag
27376
27522
  * through a `WeakMap`, like the cross-stack associations, so it dies with
27377
- * the bag and another pass's strings cannot be reached.
27523
+ * the bag. An unrelated pass cannot reach these strings; a nested child
27524
+ * whose `inheritedSecrets` is this bag reads them (`registeredLogTwin`).
27378
27525
  */
27379
27526
  rememberLogTwin(context, result, twin) {
27380
27527
  if (twin === result) return;
@@ -29149,7 +29296,7 @@ var CloudControlProvider = class {
29149
29296
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
29150
29297
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
29151
29298
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
29152
- const { ASGProvider } = await import("./asg-provider-DU7mN-cS.js").then((n) => n.n);
29299
+ const { ASGProvider } = await import("./asg-provider-JRuQeFtl.js").then((n) => n.n);
29153
29300
  const asgProvider = new ASGProvider();
29154
29301
  return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
29155
29302
  }
@@ -41849,4 +41996,4 @@ var DeployEngine = class DeployEngine {
41849
41996
 
41850
41997
  //#endregion
41851
41998
  export { secretSafeKeyDisplay as $, isCrossRegionRedirect as $n, CdkdError as $r, applyRoleArnIfSet as $t, planOrphanAdoption as A, forceQuitRecoveryClause as An, resolveStateBucketWithDefaultAndSource as Ar, isSettledInstanceState as At, formatResourceLine as B, shouldRetainResource as Bn, expectedOwnerParam as Br, readConfigString as Bt, createPreDeleteFinalSnapshot as C, isRetryableTransientError as Ci, redactSecretsForState as Cn, getDefaultStateBucketName as Cr, cfnRefValueFromPhysicalId as Ct, makeCanonicalizePropertiesFn as D, markRedactedCause as Di, rebuildClientForBucketRegion as Dn, resolveCaptureObservedState as Dr, isUnboundTemplateParameter as Dt, unsupportedFinalSnapshotError as E, markNonRetryable as Ei, S3StateBackend as En, resolveAutoAssetStorage as Er, isImpossibleEmptyStoredAttribute as Et, WARM_THROUGHPUT_MEMBERS as F, exportNamesCarriedFrom as Fn, CFN_TEMPLATE_URL_LIMIT as Fr, coerceCfnBoolean as Ft, red as G, createAssetRedirectResolver as Gn, processStackMessages as Gr, classifyReplaySecretRegion as Gt, cyan as H, stringifyValue as Hn, canonicalizeRegion as Hr, requireConfigArray as Ht, coerceWarmThroughput as I, importableOutputKeys as In, MIGRATE_TMP_PREFIX as Ir, coerceCfnInteger as It, collectPublishedOutputNames as J, AssetModeResolver as Jn, AwsClients as Jr, s3BucketArn as Jt, yellow as K, loadPublishableAssetManifest as Kn, clearBucketRegionCache as Kr, producerRegionsFromState as Kt, isWarmThroughputDecrease as L, importableOutputs as Ln, findLargeInlineResources as Lr, configBooleanRefusal as Lt, isStatefulRecreateTargetForReplace as M, shellQuote as Mn, stateBucketExistenceConfirmed as Mr, normalizeAwsTagsToCfn as Mt, isStatefulRecreateTargetSync as N, CUSTOM_RESOURCE_RESPONSE_PREFIX as Nn, warnDeprecatedNoPrefixCliFlag as Nr, resolveExplicitPhysicalId as Nt, extractDeploymentEventError as O, retryClassificationText as Oi, buildForceUnlockCommand as On, resolveSkipPrefix as Or, parameterTypeMayLoseSecretIdentity as Ot, renderStatefulReason as P, DEFAULT_STATE_PREFIX as Pn, CFN_TEMPLATE_BODY_LIMIT as Pr, assertRegionMatch as Pt, secretBearingStateKeyWarning as Q, getBootstrapMarkerKey as Qn, AssetError as Qr, s3BucketWebsiteUrl as Qt, toCfnInteger as R, orphansAfterRollback as Rn, uploadCfnTemplate as Rr, configIntegerRefusal as Rt, ccRoutedFinalSnapshotError as S, isMarkedNonRetryable as Si, recoverMaskedOutput as Sn, synthesisStatusMessage as Sr, carriesDynamicReference as St, refusesFinalSnapshot as T, isTransientServerError as Ti, LockManager as Tn, resolveApp as Tr, getAccountInfo as Tt, gray as U, WorkGraph as Un, derivePartitionAndUrlSuffix as Ur, requireConfigObject as Ut, bold as V, AssetPublisher as Vn, PARTITION_TABLE as Vr, replayWarn as Vt, green as W, buildAssetRedirectMap as Wn, AssemblyReader as Wr, requireConfigString as Wt, isExportAliasCollision as X, assertAssetBucketRegion as Xn, resetAwsClients as Xr, s3BucketDualStackDomainName as Xt, exportAliasCollisionScrubWarning as Y, BOOTSTRAP_MARKER_PREFIX as Yn, getAwsClients as Yr, s3BucketDomainName as Yt, secretBearing as Z, ensureAssetStorage as Zn, setAwsClients as Zr, s3BucketRegionalDomainName as Zt, isSecretBearingReferenceString as _, SynthesisError as _i, isSingleDynamicReferenceToken as _n, escapeRegExp$1 as _r, deleteIndeterminateGuards as _t, DeploymentEventsStore as a, IntrinsicResolutionRefusalError as ai, withRetry as an, describeAwsFailure as ar, wouldReturnToSdkProvider as at, PRE_DELETE_SNAPSHOT_TYPES as b, normalizeAwsError as bi, maskSecretsInText as bn, getDockerImageBySourceHash as br, isTerminationProtectionPropagationError as bt, replayFailedOperations as c, LockError as ci, STATE_SOURCED_BASELINE_RULES as cn, describeDockerExecFailure as cr, maskerOrIdentity as ct, updatePartialReason as d, ProvisioningError as di, TEMPLATE_SOURCED_RULES as dn, formatDockerLoginError as dr, interruptWatchListenerCount as dt, ConfigError as ei, DiffCalculator as en, parseBootstrapMarker as er, getCurrentResourceSecrets as et, withResourceDeadline as f, ResourceTimeoutError as fi, carriesSecretMask as fn, getDockerCmd as fr, isInterruptedWaitError as ft, bagHoldsSecretExpression as g, StateError as gi, identityKeyFor as gn, runDockerStreaming as gr, UNSPECIFIED_SKIP_REASON as gt, computeImplicitDeleteEdges as h, StackTerminationProtectionError as hi, errorCauseChain as hn, runDockerForeground as hr, slowCcOperationTimeoutMs as ht, DeploymentEventsReader as i, DynamicReferenceRegionAmbiguousError as ii, describeTypeWithThrottleRetry as in, buildDenyExternalAccessPolicy as ir, ProviderRegistry as it, MULTI_REGION_RECREATE_BLOCKED_TYPES as j, formatLockExpiry as jn, resolveUseCdkBootstrapAssets as jr, WAFv2WebACLProvider as jt, makeSiblingClaimReader as k, __exportAll as ki, buildLockContentionMessage as kn, resolveStateBucketWithDefault as kr, refStateLookupFromResource as kt, replayRollback as l, NestedStackChildDirectDestroyError as li, STATE_SOURCED_CROSS_GENERATION_RULES as ln, describeDockerFailure as lr, beginCommandInterruptScope as lt, IMPLICIT_DELETE_DEPENDENCIES as m, StackHasActiveImportsError as mi, dynamicReferenceTokens as mn, redactDockerArgvValues as mr, CloudControlProvider as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, DependencyError as ni, findActionableSilentDrops as nn, validateAssetBucketName as nr, collectInlinePolicyNamesManagedBySiblings as nt, planFailedOps as o, LocalInvokeBuildError as oi, DagBuilder as on, buildDockerImage as or, createMaskedRetryLogger as ot, maskingRetryLogger as p, ResourceUpdateNotSupportedError as pi, createSecretMasker as pn, partitionSensitiveEnv as pr, startInterruptWatch as pt, collectDeclaredOutputNames as q, rewriteTemplateAssetReferences as qn, resolveBucketRegion as qr, withSharedDrainBudget as qt, DeployEngine as r, DeployCancelledError as ri, findSilentDropProperties as rn, validateContainerRepoName as rr, clearOnUpdateRemoval as rt, planRollback as s, LocalStartServiceError as si, TemplateParser as sn, describeDockerCapturedOutput as sr, maskDeep as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, CrossAccountSecretRefusalError as ti, INTRINSIC_KEYS as tn, readBootstrapMarkerBody as tr, IAMRoleProvider as tt, updatePartialMessage as u, PartialFailureError as ui, STATE_SOURCED_READBACK_RULES as un, dockerSpawnEnvWithSensitive as ur, endCommandInterruptScope as ut, bindingSkippedOutputs as v, formatError as vi, markSameGenerationBag as vn, stripControlChars as vr, deleteSkipReason as vt, isFinalSnapshotError as w, isThrottlingError as wi, scrubResourceRecord as wn, getLegacyStateBucketName as wr, coerceParameterTypedValue as wt, buildFinalSnapshotIdentifier as x, withErrorHandling as xi, recordMaskOnlyValue as xn, Synthesizer as xr, IntrinsicFunctionResolver as xt, ATOMIC_FINAL_SNAPSHOT_TYPES as y, isCdkdError as yi, maskSecretsInError as yn, AssetManifestLoader as yr, disableInstanceApiTermination as yt, toFiniteNumber as z, orphansCarriedFrom as zn, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as zr, configStringRefusal as zt };
41852
- //# sourceMappingURL=deploy-engine-WFO9o9M0.js.map
41999
+ //# sourceMappingURL=deploy-engine-BMp4b4Vl.js.map