@go-to-k/cdkd 0.230.3 → 0.230.5

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.
@@ -12597,6 +12597,78 @@ var DeployEngine = class {
12597
12597
  }
12598
12598
  }
12599
12599
  /**
12600
+ * Build a sibling context for the deploy-time `observedProperties`
12601
+ * capture of an IAM principal (`AWS::IAM::Role` / `::User` / `::Group`)
12602
+ * so that inline policies managed by a SEPARATE `AWS::IAM::Policy`
12603
+ * resource are filtered OUT of the captured `Policies` baseline —
12604
+ * exactly as the `cdkd drift` read path already does via
12605
+ * `buildReadCurrentStateContext`.
12606
+ *
12607
+ * Without this, the post-CREATE / post-UPDATE capture passes no
12608
+ * context, so `collectInlinePolicyNamesManagedBySiblings` no-ops. The
12609
+ * capture's `ListRolePolicies` then RACES the sibling
12610
+ * `AWS::IAM::Policy`'s `PutRolePolicy`: when the read lands after the
12611
+ * write, the sibling-managed `DefaultPolicy*` leaks into
12612
+ * `observedProperties.Policies`. A later `cdkd drift` (whose AWS-current
12613
+ * side filters it correctly) then reports phantom drift
12614
+ * `- Policies:[DefaultPolicy] / + Policies:[]` — a systemic false
12615
+ * positive that fires for essentially every Lambda / L2 construct whose
12616
+ * grant emits a `Default Policy`.
12617
+ *
12618
+ * The sibling relationship is fully determined by the TEMPLATE (which
12619
+ * `AWS::IAM::Policy` lists this principal in its `Roles`/`Users`/
12620
+ * `Groups`), so this is built from the template — deploy-order-
12621
+ * independent, immune to the race. Each matched sibling is synthesized
12622
+ * into the resolved-property shape
12623
+ * `collectInlinePolicyNamesManagedBySiblings` expects
12624
+ * (`{ [attachmentField]: [thisPrincipalPhysicalId], PolicyName }`).
12625
+ *
12626
+ * Returns `undefined` (no context) for non-IAM-principal types and when
12627
+ * no sibling policy attaches to the captured principal — both leave the
12628
+ * capture behaving exactly as before.
12629
+ */
12630
+ async buildObservedCaptureSiblings(resourceType, capturedLogicalId, capturedPhysicalId, template, stateResources, stackName, parameterValues, conditions) {
12631
+ if (this.options.captureObservedState !== true) return void 0;
12632
+ const attachmentField = resourceType === "AWS::IAM::Role" ? "Roles" : resourceType === "AWS::IAM::User" ? "Users" : resourceType === "AWS::IAM::Group" ? "Groups" : void 0;
12633
+ if (!attachmentField) return void 0;
12634
+ const resources = template?.Resources;
12635
+ if (!resources) return void 0;
12636
+ let resolverContext;
12637
+ const isRefTo = (value, logicalId) => typeof value === "object" && value !== null && !Array.isArray(value) && value["Ref"] === logicalId;
12638
+ const siblings = {};
12639
+ for (const [lid, res] of Object.entries(resources)) {
12640
+ if (lid === capturedLogicalId) continue;
12641
+ if (res.Type !== "AWS::IAM::Policy") continue;
12642
+ const props = res.Properties ?? {};
12643
+ const attachments = props[attachmentField];
12644
+ if (!Array.isArray(attachments)) continue;
12645
+ if (!attachments.some((a) => isRefTo(a, capturedLogicalId) || a === capturedPhysicalId)) continue;
12646
+ let policyName = props["PolicyName"];
12647
+ if (policyName !== void 0 && typeof policyName !== "string") {
12648
+ resolverContext ??= this.buildResolverContext({
12649
+ template,
12650
+ resources: stateResources,
12651
+ ...parameterValues && { parameters: parameterValues },
12652
+ ...conditions && { conditions }
12653
+ }, stackName);
12654
+ try {
12655
+ policyName = await this.resolver.resolve(policyName, resolverContext);
12656
+ } catch {
12657
+ continue;
12658
+ }
12659
+ }
12660
+ if (typeof policyName !== "string") continue;
12661
+ siblings[lid] = {
12662
+ resourceType: "AWS::IAM::Policy",
12663
+ properties: {
12664
+ [attachmentField]: [capturedPhysicalId],
12665
+ PolicyName: policyName
12666
+ }
12667
+ };
12668
+ }
12669
+ return Object.keys(siblings).length > 0 ? { siblings } : void 0;
12670
+ }
12671
+ /**
12600
12672
  * Kick off `provider.readCurrentState` for every resource in the
12601
12673
  * loaded state that lacks `observedProperties` (e.g. state written
12602
12674
  * by a pre-v3 binary, or a v3 record where a NO_CHANGE-skipped
@@ -13305,7 +13377,8 @@ var DeployEngine = class {
13305
13377
  ...templateAttrs,
13306
13378
  provisionedBy: createDecision.provisionedBy
13307
13379
  };
13308
- this.kickOffObservedCapture(createProvider, logicalId, result.physicalId, resourceType, resolvedProps);
13380
+ const createCaptureSiblings = await this.buildObservedCaptureSiblings(resourceType, logicalId, result.physicalId, template, stateResources, stackName, parameterValues, conditions);
13381
+ this.kickOffObservedCapture(createProvider, logicalId, result.physicalId, resourceType, resolvedProps, createCaptureSiblings);
13309
13382
  if (counts) counts.created++;
13310
13383
  if (progress) progress.current++;
13311
13384
  const createPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
@@ -13468,7 +13541,8 @@ var DeployEngine = class {
13468
13541
  ...this.extractTemplateAttributes(template, logicalId),
13469
13542
  provisionedBy: resultProvisionedBy
13470
13543
  };
13471
- this.kickOffObservedCapture(updateProvider, logicalId, result.physicalId, resourceType, resolvedProps);
13544
+ const updateCaptureSiblings = await this.buildObservedCaptureSiblings(resourceType, logicalId, result.physicalId, template, stateResources, stackName, parameterValues, conditions);
13545
+ this.kickOffObservedCapture(updateProvider, logicalId, result.physicalId, resourceType, resolvedProps, updateCaptureSiblings);
13472
13546
  if (counts) counts.updated++;
13473
13547
  if (progress) progress.current++;
13474
13548
  const updatePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
@@ -13710,4 +13784,4 @@ var DeployEngine = class {
13710
13784
 
13711
13785
  //#endregion
13712
13786
  export { CFN_TEMPLATE_BODY_LIMIT as $, LockManager as A, runDockerForeground as B, findActionableSilentDrops as C, DiffCalculator as D, applyRoleArnIfSet as E, stringifyValue as F, getDefaultStateBucketName as G, AssetManifestLoader as H, WorkGraph as I, resolveCaptureObservedState as J, getLegacyStateBucketName as K, buildDockerImage as L, rebuildClientForBucketRegion as M, shouldRetainResource as N, DagBuilder as O, AssetPublisher as P, warnDeprecatedNoPrefixCliFlag as Q, formatDockerLoginError as R, ProviderRegistry as S, IntrinsicFunctionResolver as T, getDockerImageBySourceHash as U, runDockerStreaming as V, Synthesizer as W, resolveStateBucketWithDefault as X, resolveSkipPrefix as Y, resolveStateBucketWithDefaultAndSource as Z, green as _, withRetry as a, clearBucketRegionCache as at, IAMRoleProvider as b, computeImplicitDeleteEdges as c, isStatefulRecreateTargetSync as d, CFN_TEMPLATE_URL_LIMIT as et, renderStatefulReason as f, gray as g, cyan as h, withResourceDeadline as i, AssemblyReader as it, S3StateBackend as j, TemplateParser as k, extractDeploymentEventError as l, bold as m, DEFAULT_RESOURCE_WARN_AFTER_MS as n, findLargeInlineResources as nt, isRetryableTransientError as o, resolveBucketRegion as ot, formatResourceLine as p, resolveApp as q, DeployEngine as r, uploadCfnTemplate as rt, IMPLICIT_DELETE_DEPENDENCIES as s, DEFAULT_RESOURCE_TIMEOUT_MS as t, MIGRATE_TMP_PREFIX as tt, MULTI_REGION_RECREATE_BLOCKED_TYPES as u, red as v, CloudControlProvider as w, collectInlinePolicyNamesManagedBySiblings as x, yellow as y, getDockerCmd as z };
13713
- //# sourceMappingURL=deploy-engine-BGL0DPBv.js.map
13787
+ //# sourceMappingURL=deploy-engine-DP5yW4f5.js.map