@go-to-k/cdkd 0.290.16 → 0.290.17

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-1FTpsWNc.js";
2
+ import { n as isVersionOnlyInvocation, t as getCdkdVersion } from "./version-CT2xso6V.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-U03H43s7.js");
77
+ const { buildProgram } = await import("./program-CbHndlOj.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 { C as displaySafe, S 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 UNRENDERABLE, y as withoutGeneratedFallbackName } from "./logger-C17H06QA.js";
2
2
  import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
3
- import { t as getCdkdVersion } from "./version-1FTpsWNc.js";
3
+ import { t as getCdkdVersion } from "./version-CT2xso6V.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";
@@ -15989,11 +15989,31 @@ function errorCauseChain(root) {
15989
15989
  * Returns the ORIGINAL object by identity when NOTHING ANYWHERE IN THE CHAIN
15990
15990
  * changed, so a non-secret failure keeps referential equality and the common
15991
15991
  * path allocates nothing.
15992
- */
15993
- function maskSecretsInError(error, secrets) {
15994
- if (secrets.size === 0 || !(error instanceof Error)) return error;
15992
+ *
15993
+ * `extraMask` is an OPTIONAL text transform run on every link's `message` and
15994
+ * `stack` BEFORE the bag pass, for the class the bag structurally cannot reach
15995
+ * (issue [#3234](https://github.com/go-to-k/cdkd/issues/3234)): a name masked
15996
+ * BY POSITION rather than by value. A bag masks a sub-`MIN_NEEDLE_LENGTH`
15997
+ * plaintext only as the WHOLE text, so a 1-3 character secret EMBEDDED in a
15998
+ * longer name that another module quoted back is invisible here — while the
15999
+ * caller that resolved the name holds both it and its masked log text and can
16000
+ * substitute one for the other exactly. BEFORE rather than after, because the
16001
+ * substitution matches the RAW name: a bag pass that had already rewritten part
16002
+ * of it would leave nothing for the transform to find.
16003
+ *
16004
+ * It is a pure `(text) => text` so this module stays a no-import LEAF. With
16005
+ * `extraMask` supplied the empty-bag short-circuit no longer applies — an empty
16006
+ * bag plus a positional transform still has work to do.
16007
+ *
16008
+ * THE BOUND, unchanged by `extraMask`: a thrown value that is not an `Error`
16009
+ * is handed back BY IDENTITY and masked by neither pass. A caller whose
16010
+ * callees can reject with a non-`Error` owes that case its own handling.
16011
+ */
16012
+ function maskSecretsInError(error, secrets, extraMask) {
16013
+ if (!(error instanceof Error) || secrets.size === 0 && !extraMask) return error;
16014
+ const maskText = (text) => maskSecretsInText(extraMask ? extraMask(text) : text, secrets);
15995
16015
  const chain = errorCauseChain(error);
15996
- const maskedMessages = chain.map((link) => maskSecretsInText(link.message, secrets));
16016
+ const maskedMessages = chain.map((link) => maskText(link.message));
15997
16017
  if (maskedMessages.every((masked, i) => masked === chain[i].message)) return error;
15998
16018
  const clones = /* @__PURE__ */ new Map();
15999
16019
  for (const [i, original] of chain.entries()) {
@@ -16012,7 +16032,7 @@ function maskSecretsInError(error, secrets) {
16012
16032
  });
16013
16033
  const originalStack = original.stack;
16014
16034
  if (typeof originalStack === "string") Object.defineProperty(clone, "stack", {
16015
- value: maskSecretsInText(originalStack, secrets),
16035
+ value: maskText(originalStack),
16016
16036
  writable: true,
16017
16037
  enumerable: false,
16018
16038
  configurable: true
@@ -27186,7 +27206,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27186
27206
  return await fetch;
27187
27207
  } catch (error) {
27188
27208
  const message = error instanceof Error ? error.message : String(error);
27189
- this.logger.warn(`Fn::GetStackOutput: CloudFormation DescribeStacks fallback failed for stack '${this.maskSecretsForLog(stackName, context)}' (${this.maskSecretsForLog(loggedRegionText, context)}): ${this.maskSecretsForLog(message, context)}. Grant cloudformation:DescribeStacks to resolve outputs from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
27209
+ const cfnNameMask = this.positionalNameMask([[stackName, this.maskSecretsForLog(stackName, context)], [region, this.maskSecretsForLog(loggedRegionText, context)]]);
27210
+ this.logger.warn(`Fn::GetStackOutput: CloudFormation DescribeStacks fallback failed for stack '${this.maskSecretsForLog(stackName, context)}' (${this.maskSecretsForLog(loggedRegionText, context)}): ${this.maskSecretsForLog(cfnNameMask ? cfnNameMask(message) : message, context)}. Grant cloudformation:DescribeStacks to resolve outputs from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
27190
27211
  return;
27191
27212
  }
27192
27213
  }
@@ -27311,7 +27332,12 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27311
27332
  const loggedOutputName = this.maskSecretsForLog(outputName, context);
27312
27333
  const loggedRegion = this.maskSecretsForLog(loggedRegionText, context);
27313
27334
  this.logger.debug(`Resolving Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${roleArn}` : ""}`);
27314
- const stateData = roleArn ? await this.getCrossAccountStackState(roleArn, stackName, region, context) : await this.getSameAccountStackState(stackName, region, context);
27335
+ let stateData;
27336
+ try {
27337
+ stateData = roleArn ? await this.getCrossAccountStackState(roleArn, stackName, region, context) : await this.getSameAccountStackState(stackName, region, context);
27338
+ } catch (error) {
27339
+ this.maskStateReadError(error, [[stackName, loggedStackName], [region, loggedRegion]], context);
27340
+ }
27315
27341
  if (!stateData) {
27316
27342
  if (!roleArn && this.cfnFallback) {
27317
27343
  const cfnOutputs = await this.lookupCfnStackOutputs(stackName, region, context, loggedRegionText);
@@ -27360,6 +27386,98 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27360
27386
  });
27361
27387
  }
27362
27388
  /**
27389
+ * A text transform replacing each RAW name this frame handed to another
27390
+ * module with the masked spelling it holds for it (issue
27391
+ * [#3234](https://github.com/go-to-k/cdkd/issues/3234)), or `undefined` when
27392
+ * no pair carries a mask.
27393
+ *
27394
+ * This is what the BAGS structurally cannot do. A bag masks by VALUE, and a
27395
+ * plaintext shorter than `MIN_NEEDLE_LENGTH` matches only as the WHOLE text,
27396
+ * so a 1-3 character secret an `Fn::Sub` assembled into a longer name is
27397
+ * invisible to it — while this frame knows the exact spans.
27398
+ *
27399
+ * A pair that DOES carry a mask contributes its raw spelling AND the spelling
27400
+ * the reader will actually see. `S3StateBackend` prints names through
27401
+ * `displaySafe(..., { asciiOnly: true })`, which REPLACES every non-printable
27402
+ * character with a space and then trims, so a secret carrying one is a
27403
+ * DIFFERENT string by the time it is quoted back and matching the raw form
27404
+ * alone would miss it while reporting success — the one-string-space rule
27405
+ * `outputs-export-alias.ts` states for its own scan: the text that was tested
27406
+ * and the text that is printed must be the same text. The CloudFormation
27407
+ * fallback does NOT sanitize (it rethrows the SDK's message as it is), so the
27408
+ * second spelling is inert at that call site and costs one comparison.
27409
+ *
27410
+ * NO MINIMUM LENGTH beyond non-empty, deliberately. A one-character masked
27411
+ * name rewrites every occurrence of that character in the sentence
27412
+ * (`a` -> `***` turns `us-east-1` into `us-e***st-1`), which is unreadable
27413
+ * but SAFE — the direction this function must never get wrong is printing
27414
+ * too little, not too much, and a floor here would be a floor on masking.
27415
+ *
27416
+ * `raw !== ''` is DEFENSIVE, and it is NOT the guard that handles a name
27417
+ * whose sanitized form is empty — that one inspects `shown`, below, and its
27418
+ * own comment says why. What this clause is not is redundant against
27419
+ * `raw !== masked`: `rememberLogTwin` has no empty-key guard and
27420
+ * `splitLogTwins` registers every piece it produces, so `registeredLogTwin`
27421
+ * can answer `***` for the empty string and make `maskSecretsForLog('')`
27422
+ * differ from `''`. Neither call site can reach it — both refuse an empty
27423
+ * name upstream — so it fences nothing measured today.
27424
+ *
27425
+ * LONGEST KEY FIRST — over every key, raw and sanitized alike, which is what
27426
+ * the comparator sees — so a key that contains another is rewritten as itself
27427
+ * rather than having the inner one replaced underneath it. **That ordering
27428
+ * is DEFENSIVE and this suite does not distinguish it** — measured: reversing
27429
+ * the comparator leaves every case green. The reason is that no case here
27430
+ * builds two raws that NEST: the one case with two surviving pairs masks a
27431
+ * stack name and a region that share no substring, and everywhere else one
27432
+ * pair is dropped for carrying no mask. It earns its place on the shape that
27433
+ * DOES diverge — a shorter raw whose mask is not a prefix of the longer's
27434
+ * (`q7` -> `***` beside `q7x` -> `***` turns `q7x` into `***x` shortest-first,
27435
+ * leaking the `x`) — which needs two separately recorded secrets, one of them
27436
+ * masked WHOLE, and is not constructed here. Recorded as measured rather than
27437
+ * claimed fenced.
27438
+ */
27439
+ positionalNameMask(pairs) {
27440
+ const substitutions = pairs.filter(([raw, masked]) => raw !== "" && raw !== masked).flatMap(([raw, masked]) => {
27441
+ const shown = displaySafe(raw, { asciiOnly: true });
27442
+ if (shown === raw) return [[raw, masked]];
27443
+ const shownMask = displaySafe(masked, { asciiOnly: true });
27444
+ return shown === "" || shownMask === "" ? [[raw, masked]] : [[raw, masked], [shown, shownMask]];
27445
+ }).sort(([a], [b]) => b.length - a.length);
27446
+ if (substitutions.length === 0) return void 0;
27447
+ return (text) => {
27448
+ let out = text;
27449
+ for (const [raw, masked] of substitutions) out = out.split(raw).join(masked);
27450
+ return out;
27451
+ };
27452
+ }
27453
+ /**
27454
+ * Mask a failure raised by a module this resolver handed RAW names to (issue
27455
+ * [#3234](https://github.com/go-to-k/cdkd/issues/3234)).
27456
+ *
27457
+ * Returns a masked CLONE of the whole cause chain, not a new wrapper, and
27458
+ * that is the point: `formatError` renders `Caused by: <cause>`, so masking
27459
+ * only a fresh top-level message leaves the original message one link down
27460
+ * and prints it anyway. The clone keeps the class, every own descriptor
27461
+ * (`markNonRetryable`'s non-enumerable symbol, `$metadata`, `Code`, `name`)
27462
+ * and the chain shape, so every reader that classifies this error still
27463
+ * does — see `maskSecretsInError`'s own doc.
27464
+ *
27465
+ * `pairs` are (raw, masked-log-text) for the names this frame handed over;
27466
+ * {@link positionalNameMask} turns them into the transform and owns why.
27467
+ */
27468
+ maskStateReadError(error, pairs, context) {
27469
+ const extraMask = this.positionalNameMask(pairs);
27470
+ let masked = error;
27471
+ let positional = extraMask;
27472
+ for (const bag of [context?.inheritedSecrets, context?.recordedSecretValues]) {
27473
+ if (!bag || bag.size === 0) continue;
27474
+ masked = maskSecretsInError(masked, bag, positional);
27475
+ positional = void 0;
27476
+ }
27477
+ if (positional) masked = maskSecretsInError(masked, /* @__PURE__ */ new Map(), positional);
27478
+ throw masked;
27479
+ }
27480
+ /**
27363
27481
  * Read the producer's state from the SAME AWS account (no RoleArn).
27364
27482
  *
27365
27483
  * Uses the consumer's shared `context.stateBackend` — the same backend
@@ -29652,7 +29770,7 @@ var CloudControlProvider = class {
29652
29770
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
29653
29771
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
29654
29772
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
29655
- const { ASGProvider } = await import("./asg-provider-CvkcE8rH.js").then((n) => n.n);
29773
+ const { ASGProvider } = await import("./asg-provider-BPBdAAGQ.js").then((n) => n.n);
29656
29774
  const asgProvider = new ASGProvider();
29657
29775
  return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
29658
29776
  }
@@ -42413,4 +42531,4 @@ var DeployEngine = class DeployEngine {
42413
42531
 
42414
42532
  //#endregion
42415
42533
  export { secretBearing as $, BOOTSTRAP_MARKER_PREFIX as $n, getAwsClients as $r, s3BucketRegionalDomainName as $t, extractDeploymentEventError as A, markNonRetryable as Ai, buildForceUnlockCommand as An, resolveAutoAssetStorage as Ar, parameterTypeMayLoseSecretIdentity as At, toCfnInteger as B, importableOutputs as Bn, MIGRATE_TMP_PREFIX as Br, configIntegerRefusal as Bt, buildFinalSnapshotIdentifier as C, isCdkdError as Ci, recordMaskOnlyValue as Cn, AssetManifestLoader as Cr, IntrinsicFunctionResolver as Ct, refusesFinalSnapshot as D, isRetryableTransientError as Di, LockManager as Dn, getDefaultStateBucketName as Dr, getAccountInfo as Dt, isFinalSnapshotError as E, isMarkedNonRetryable as Ei, scrubResourceRecord as En, synthesisStatusMessage as Er, coerceParameterTypedValue as Et, isStatefulRecreateTargetSync as F, CUSTOM_RESOURCE_RESPONSE_PREFIX as Fn, resolveUseCdkBootstrapAssets as Fr, resolveExplicitPhysicalId as Ft, gray as G, AssetPublisher as Gn, PARTITION_TABLE as Gr, requireConfigObject as Gt, formatResourceLine as H, orphansAfterRollback as Hn, uploadCfnTemplate as Hr, readConfigString as Ht, renderStatefulReason as I, DEFAULT_STATE_PREFIX as In, stateBucketExistenceConfirmed as Ir, assertRegionMatch as It, yellow as J, buildAssetRedirectMap as Jn, AssemblyReader as Jr, producerRegionsFromState as Jt, green as K, stringifyValue as Kn, canonicalizeRegion as Kr, requireConfigString as Kt, WARM_THROUGHPUT_MEMBERS as L, exportNamesCarriedFrom as Ln, warnDeprecatedNoPrefixCliFlag as Lr, coerceCfnBoolean as Lt, planOrphanAdoption as M, retryClassificationText as Mi, forceQuitRecoveryClause as Mn, resolveSkipPrefix as Mr, isSettledInstanceState as Mt, MULTI_REGION_RECREATE_BLOCKED_TYPES as N, __exportAll as Ni, formatLockExpiry as Nn, resolveStateBucketWithDefault as Nr, WAFv2WebACLProvider as Nt, unsupportedFinalSnapshotError as O, isThrottlingError as Oi, S3StateBackend as On, getLegacyStateBucketName as Or, isImpossibleEmptyStoredAttribute as Ot, isStatefulRecreateTargetForReplace as P, shellQuote as Pn, resolveStateBucketWithDefaultAndSource as Pr, normalizeAwsTagsToCfn as Pt, isExportAliasCollision as Q, AssetModeResolver as Qn, AwsClients as Qr, s3BucketDualStackDomainName as Qt, coerceWarmThroughput as R, hasReadableExportSet as Rn, CFN_TEMPLATE_BODY_LIMIT as Rr, coerceCfnInteger as Rt, PRE_DELETE_SNAPSHOT_TYPES as S, formatError as Si, maskSecretsInText as Sn, stripControlChars as Sr, isTerminationProtectionPropagationError as St, createPreDeleteFinalSnapshot as T, withErrorHandling as Ti, redactSecretsForState as Tn, Synthesizer as Tr, cfnRefValueFromPhysicalId as Tt, bold as U, orphansCarriedFrom as Un, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Ur, replayWarn as Ut, toFiniteNumber as V, isReadableBag as Vn, findLargeInlineResources as Vr, configStringRefusal as Vt, cyan as W, shouldRetainResource as Wn, expectedOwnerParam as Wr, requireConfigArray as Wt, collectPublishedOutputNames as X, loadPublishableAssetManifest as Xn, clearBucketRegionCache as Xr, s3BucketArn as Xt, collectDeclaredOutputNames as Y, createAssetRedirectResolver as Yn, processStackMessages as Yr, withSharedDrainBudget as Yt, exportAliasCollisionScrubWarning as Z, rewriteTemplateAssetReferences as Zn, resolveBucketRegion as Zr, s3BucketDomainName as Zt, isSecretBearingReferenceString as _, ResourceUpdateNotSupportedError as _i, errorCauseChain as _n, partitionSensitiveEnv as _r, slowCcOperationTimeoutMs as _t, DeploymentEventsStore as a, CrossAccountSecretRefusalError as ai, findSilentDropProperties as an, readBootstrapMarkerBody as ar, clearOnUpdateRemoval as at, bindingSkippedOutputs as b, StateError as bi, markSameGenerationBag as bn, runDockerStreaming as br, deleteSkipReason as bt, replayFailedOperations as c, DynamicReferenceRegionAmbiguousError as ci, DagBuilder as cn, buildDenyExternalAccessPolicy as cr, createMaskedRetryLogger as ct, updatePartialReason as d, LocalStartServiceError as di, STATE_SOURCED_CROSS_GENERATION_RULES as dn, describeDockerCapturedOutput as dr, beginCommandInterruptScope as dt, resetAwsClients as ei, s3BucketWebsiteUrl as en, assertAssetBucketRegion as er, secretBearingStateKeyWarning as et, withResourceDeadline as f, LockError as fi, STATE_SOURCED_READBACK_RULES as fn, describeDockerExecFailure as fr, endCommandInterruptScope as ft, bagHoldsSecretExpression as g, ResourceTimeoutError as gi, dynamicReferenceTokens as gn, getDockerCmd as gr, CloudControlProvider as gt, computeImplicitDeleteEdges as h, ProvisioningError as hi, createSecretMasker as hn, formatDockerLoginError as hr, startInterruptWatch as ht, DeploymentEventsReader as i, ConfigError as ii, findActionableSilentDrops as in, parseBootstrapMarker as ir, collectInlinePolicyNamesManagedBySiblings as it, makeSiblingClaimReader as j, markRedactedCause as ji, buildLockContentionMessage as jn, resolveCaptureObservedState as jr, refStateLookupFromResource as jt, makeCanonicalizePropertiesFn as k, isTransientServerError as ki, rebuildClientForBucketRegion as kn, resolveApp as kr, isUnboundTemplateParameter as kt, replayRollback as l, IntrinsicResolutionRefusalError as li, TemplateParser as ln, describeAwsFailure as lr, maskDeep as lt, IMPLICIT_DELETE_DEPENDENCIES as m, PartialFailureError as mi, carriesSecretMask as mn, dockerSpawnEnvWithSensitive as mr, isInterruptedWaitError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, AssetError as ni, DiffCalculator as nn, getBootstrapMarkerKey as nr, getCurrentResourceSecrets as nt, planFailedOps as o, DependencyError as oi, describeTypeWithThrottleRetry as on, validateAssetBucketName as or, ProviderRegistry as ot, maskingRetryLogger as p, NestedStackChildDirectDestroyError as pi, TEMPLATE_SOURCED_RULES as pn, describeDockerFailure as pr, interruptWatchListenerCount as pt, red as q, WorkGraph as qn, derivePartitionAndUrlSuffix as qr, classifyReplaySecretRegion as qt, DeployEngine as r, CdkdError as ri, INTRINSIC_KEYS as rn, isCrossRegionRedirect as rr, IAMRoleProvider as rt, planRollback as s, DeployCancelledError as si, withRetry as sn, validateContainerRepoName as sr, wouldReturnToSdkProvider as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, setAwsClients as ti, applyRoleArnIfSet as tn, ensureAssetStorage as tr, secretSafeKeyDisplay as tt, updatePartialMessage as u, LocalInvokeBuildError as ui, STATE_SOURCED_BASELINE_RULES as un, buildDockerImage as ur, maskerOrIdentity as ut, keptWholeReasonText as v, StackHasActiveImportsError as vi, identityKeyFor as vn, redactDockerArgvValues as vr, UNSPECIFIED_SKIP_REASON as vt, ccRoutedFinalSnapshotError as w, normalizeAwsError as wi, recoverMaskedOutput as wn, getDockerImageBySourceHash as wr, carriesDynamicReference as wt, ATOMIC_FINAL_SNAPSHOT_TYPES as x, SynthesisError as xi, maskSecretsInError as xn, escapeRegExp$1 as xr, disableInstanceApiTermination as xt, mergeNoChangeOutputs as y, StackTerminationProtectionError as yi, isSingleDynamicReferenceToken as yn, runDockerForeground as yr, deleteIndeterminateGuards as yt, isWarmThroughputDecrease as z, importableOutputKeys as zn, CFN_TEMPLATE_URL_LIMIT as zr, configBooleanRefusal as zt };
42416
- //# sourceMappingURL=deploy-engine-B91NMqm1.js.map
42534
+ //# sourceMappingURL=deploy-engine-BYTwDxet.js.map