/** * Destroy pre-flight — ONE pass over EVERY stack about to be destroyed, * BEFORE the first destructive mutation. The destroy engine empties * pre-empty-tagged S3 buckets before each CDK delete, so a delete-refusing * guard (RDS DeletionProtection — fjall's own database constructs default it * ON — DynamoDB DeletionProtectionEnabled, or an ELBv2 load balancer's * `deletion_protection.enabled`, both ON at the resilient and enterprise * backup tiers) discovered mid-run would leave the application * half-destroyed: buckets emptied, stack DELETE_FAILED, raw CFN error * surfaced. * * The pass probes every guard first and switches each enabled one OFF * itself, then re-probes until the flip has landed: the destroy is consented * (CLI confirmation, a CI pipeline's destroy action, a webapp job) and the * guard exists to stop an unintended delete, not the deliberate one. Every * flip is reported through `onLog` — the only sink a CI log or worker * transcript has for "fjall changed this setting" — carrying the status * sequence the disable observed where it had to wait on the service, and how * long the guard then took to read as off, so the transition is measured on * every destroy rather than assumed. The * recreate pre-flight shares the registry but keeps halting: a deploy never * removes a guard. * * Fail-closed polarity (matching the recreate pre-flight, opposite of the * drift preFlightGate): an unverifiable resource, a refused modify, or a * flip that never settles blocks the destroy, because proceeding risks * partial data loss rather than a merely stale answer. The halt names the * manual cure. Already-deleted stacks are the sanctioned exception — the * destroy engine converts them to skipped, so a missing stack has nothing * to block. * * Failure messages are pre-masked at construction (identifier-only content * plus masked SDK error text). */ import { type Result } from "@fjall/generator"; import type { AwsProvider } from "../../aws/AwsProvider.js"; import type { DeployCallbacks } from "../../types/callbacks.js"; import { type DeleteBlockDisableTiming } from "../probes/deleteBlockProbes.js"; export interface RunDestroyPreFlightParams { /** EVERY stack the destroy will touch — the pass must clear all of them * before the engine mutates any. */ stackNames: readonly string[]; abortSignal?: AbortSignal; /** Visible sink for every guard the pre-flight switches off. */ onLog?: DeployCallbacks["onLog"]; /** Wait/poll bounds for the disable and its settle re-probe; the registry * default in production, shortened by tests. */ timing?: DeleteBlockDisableTiming; } /** * Run the delete-block probe over every live resource (in every stack about * to be destroyed) whose type carries a registry entry, switching off every * guard found. The first failure aborts the whole destroy before any stack * or bucket is touched. */ export declare function runDestroyPreFlight(aws: AwsProvider, params: RunDestroyPreFlightParams): Promise>;