@go-to-k/cdkd 0.57.1 → 0.58.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.
package/README.md CHANGED
@@ -487,6 +487,33 @@ Two `orphan` variants at different granularities:
487
487
  Both `cdkd destroy` (synth-driven) and `cdkd state destroy`
488
488
  (state-driven, no synth) delete AWS resources + state.
489
489
 
490
+ ## Stack termination protection
491
+
492
+ CDK's `new Stack(app, 'X', { terminationProtection: true })` is
493
+ honored by `cdkd destroy` and `cdkd destroy --all`. A protected
494
+ stack is refused before the lock is acquired and before any
495
+ per-resource delete runs; in `--all` runs sibling unprotected
496
+ stacks still destroy and the protected ones contribute to the
497
+ partial-failure exit code 2.
498
+
499
+ Bypass workflow:
500
+
501
+ 1. Edit the CDK code to set `terminationProtection: false`.
502
+ 2. Redeploy: `cdkd deploy MyStack`.
503
+ 3. Retry: `cdkd destroy MyStack`.
504
+
505
+ `cdkd state destroy` (state-only, no synth) does **not** honor
506
+ `terminationProtection` — the flag is a CDK property surfaced via
507
+ synth and is not stored in cdkd's state.json. Use `cdkd destroy`
508
+ when synth is available, or accept that `state destroy` is the
509
+ explicit "I know what I'm doing, ignore CDK guards" escape hatch.
510
+
511
+ A future `--remove-protection` flag (separate scope) will provide
512
+ an explicit one-shot bypass without editing CDK code.
513
+
514
+ `cdkd diff` (read-only) and `cdkd deploy` (forward-only) are
515
+ unaffected — only destroy is gated.
516
+
490
517
  ## `publish-assets`: synth + build + publish, no deploy
491
518
 
492
519
  `cdkd publish-assets` runs the asset half of the deploy pipeline
package/dist/cli.js CHANGED
@@ -1207,6 +1207,18 @@ var ResourceUpdateNotSupportedError = class _ResourceUpdateNotSupportedError ext
1207
1207
  }
1208
1208
  exitCode = 2;
1209
1209
  };
1210
+ var StackTerminationProtectionError = class _StackTerminationProtectionError extends CdkdError {
1211
+ constructor(stackName, cause) {
1212
+ super(
1213
+ `Stack '${stackName}' has terminationProtection: true and cannot be destroyed. Set terminationProtection: false in the CDK code, redeploy, then retry 'cdkd destroy ${stackName}'.`,
1214
+ "STACK_TERMINATION_PROTECTION",
1215
+ cause
1216
+ );
1217
+ this.stackName = stackName;
1218
+ this.name = "StackTerminationProtectionError";
1219
+ Object.setPrototypeOf(this, _StackTerminationProtectionError.prototype);
1220
+ }
1221
+ };
1210
1222
  function isCdkdError(error) {
1211
1223
  return error instanceof CdkdError;
1212
1224
  }
@@ -1915,7 +1927,10 @@ var AssemblyReader = class {
1915
1927
  assetManifestPath,
1916
1928
  dependencyNames,
1917
1929
  region: env?.region !== "unknown-region" ? env?.region : void 0,
1918
- account: env?.account !== "unknown-account" ? env?.account : void 0
1930
+ account: env?.account !== "unknown-account" ? env?.account : void 0,
1931
+ ...props?.terminationProtection !== void 0 && {
1932
+ terminationProtection: props.terminationProtection
1933
+ }
1919
1934
  };
1920
1935
  }
1921
1936
  /**
@@ -43237,7 +43252,10 @@ async function destroyCommand(stackArgs, options) {
43237
43252
  appStacks = result.stacks.map((s) => ({
43238
43253
  stackName: s.stackName,
43239
43254
  displayName: s.displayName,
43240
- ...s.region && { region: s.region }
43255
+ ...s.region && { region: s.region },
43256
+ ...s.terminationProtection !== void 0 && {
43257
+ terminationProtection: s.terminationProtection
43258
+ }
43241
43259
  }));
43242
43260
  } catch {
43243
43261
  logger.debug("Could not synthesize app, falling back to state-based stack list");
@@ -43296,6 +43314,12 @@ Preparing to destroy stack: ${stackName}`);
43296
43314
  const refs = stateRefsByName.get(stackName) ?? [];
43297
43315
  const synthStack = appStacks.find((s) => s.stackName === stackName);
43298
43316
  const synthRegion = synthStack?.region;
43317
+ if (synthStack?.terminationProtection === true) {
43318
+ const err = new StackTerminationProtectionError(stackName);
43319
+ logger.error(` \u2717 ${err.message}`);
43320
+ totalErrors++;
43321
+ continue;
43322
+ }
43299
43323
  let stackTargetRegion;
43300
43324
  if (refs.length === 0) {
43301
43325
  logger.warn(`No state found for stack ${stackName}, skipping`);
@@ -46334,7 +46358,7 @@ function reorderArgs(argv) {
46334
46358
  }
46335
46359
  async function main() {
46336
46360
  const program = new Command14();
46337
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.57.1");
46361
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.58.0");
46338
46362
  program.addCommand(createBootstrapCommand());
46339
46363
  program.addCommand(createSynthCommand());
46340
46364
  program.addCommand(createListCommand());