-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
When strata apply or strata generate produce migrations containing destructive changes (table drops, column drops, type changes, etc.), the only control mechanism is the --allow-destructive flag. Without the flag, execution stops with an error. But when the flag is provided, everything executes without any confirmation. An interactive confirmation step is missing to prevent accidental operations in production.
Proposed Solution
Display an interactive confirmation prompt before executing operations that include destructive changes. In CI/CD environments, --yes / --force flags allow skipping the prompt.
Confirmation Flow
⚠️ Destructive Changes Detected
─────────────────────────────────
The following destructive operations will be performed:
🗑️ DROP TABLE: legacy_users
🗑️ DROP COLUMN: users.old_email
♻️ RECREATE ENUM: user_status (values changed)
These operations are IRREVERSIBLE and may cause data loss.
Do you want to proceed? [y/N]:
Implementation Plan
-
Confirmation prompt module (
src/cli/src/cli/commands/prompt.rs— new)pub struct ConfirmationPrompt { pub title: String, pub items: Vec<DestructiveItem>, pub default_no: bool, // Default is deny } impl ConfirmationPrompt { pub fn confirm(&self) -> Result<bool>; }
-
CLI flag additions
--yes/-y: Skip confirmation (for CI/CD)- Combine with existing
--allow-destructive
-
Changes to apply command (
src/cli/src/cli/commands/apply.rs)- Show prompt when
DestructiveChangeDetectorresult is non-empty - Skip prompt when
--yesflag is present - Require
--yeswhen stdin is not a TTY (pipe input)
- Show prompt when
-
Changes to generate command (
src/cli/src/cli/commands/generate.rs)- Show prompt when generating SQL with destructive changes
-
Interactive init command (
src/cli/src/cli/commands/init.rs)- Interactive dialect selection and directory name input
--yesuses all default values
TTY Detection
use std::io::IsTerminal;
fn should_prompt(yes_flag: bool) -> bool {
!yes_flag && std::io::stdin().is_terminal()
}Files Affected
src/cli/src/cli/commands/prompt.rs(new)src/cli/src/cli/commands/apply.rs— Add confirmation flowsrc/cli/src/cli/commands/generate.rs— Add confirmation flowsrc/cli/src/cli/commands/init.rs— Interactive initializationsrc/cli/src/cli/cli.rs—--yesglobal argument
Alternatives Considered
--forceflag only: A flag-only approach still risks accidental misuse- Mandatory
--dry-runfirst: Requiring--dry-runbefore destructive changes makes the workflow cumbersome
Additional Context
- Corresponds to "Require explicit flags for destructive operations" and "Add interactive prompts for initialization and dangerous operations" in ROADMAP.md
DestructiveChangeDetectorandDestructiveChangeReportare already implemented, making detection result reuse straightforwardstd::io::IsTerminalis stabilized since Rust 1.70+