Skip to content

fix: unify safety confirmation guards - #667

Merged
debba merged 2 commits into
mainfrom
fix/safety-confirmation-guards
Aug 19, 2026
Merged

fix: unify safety confirmation guards#667
debba merged 2 commits into
mainfrom
fix/safety-confirmation-guards

Conversation

@debba

@debba debba commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • disable the five-second destructive-query countdown by default and expose it as a persisted safety-confirmation setting
  • reuse the optional delay for production-write confirmations
  • suppress the standard dangerous-query modal on production connections so only the production warning is shown
  • run production guards before standard dangerous-query guards across editor, batch, notebook, and AI-generated query execution paths
  • add localized setting copy and regression coverage for guard ordering, production countdowns, environment detection, and persistence

Validation

  • pnpm test --run — 228 files, 3822 tests passed
  • pnpm exec tsc --noEmit
  • ESLint on changed TypeScript sources
  • cargo test --manifest-path src-tauri/Cargo.toml config::tests --lib — 17 tests passed
  • rustfmt --check --edition 2021 src-tauri/src/config.rs
  • git diff --check

Risk

GitNexus reports CRITICAL impact because the centralized runQuery path has 11 direct callers. The behavior change is limited to safety-guard ordering and is covered by a dedicated query-guard pipeline test.

@kilo-code-bot

kilo-code-bot Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

The PR unifies safety-confirmation guards behind a shared useQueryGuards hook that composes the production-write guard and the dangerous-query guard in the correct order (production first, short-circuits on block), and gates the 5-second confirmation countdown behind a persisted safetyConfirmationDelayEnabled setting (default off).

Incremental verification (commit 16b5e2b)

  • The new useQueryGuards hook correctly composes useProductionGuard + useDangerousQueryGuard(!isProduction) and exposes a single guardQuery(sql | string[]) gate. Batch SQL is joined with ;\n for the production guard while the original array is preserved for dangerous-statement classification.
  • No stale closures: the hook's guardQuery deps are [connectionId, guardDangerousQuery, guardProductionWrite]; useDangerousQueryGuard refreshes its guardQuery identity when enabled (= !isProduction) changes, so the composed gate always sees the current production flag.
  • No state split: Editor.tsx still calls useProductionGuard() directly for the unchanged grid-save and AI-insert paths, and useQueryGuards calls it internally for runQuery/runMultipleQueries — both consume the same ProductionGuardContext, so the modal state stays shared.
  • NotebookView.tsx is fully migrated to useQueryGuards, with guardQueryExecution included in the runCell dependency array.
  • New tests/hooks/useQueryGuards.test.ts covers guard ordering, prod-guard short-circuit, disabled dangerous guard on production connections, and batch SQL serialization.
Files Reviewed (27 files)
  • src-tauri/src/config.rs
  • src/components/notebook/NotebookView.tsx
  • src/components/settings/GeneralTab.tsx
  • src/contexts/ProductionGuardContext.tsx
  • src/contexts/SettingsContext.ts
  • src/hooks/useDangerousQueryGuard.ts
  • src/hooks/useQueryGuards.ts
  • src/i18n/locales/de.json
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/it.json
  • src/i18n/locales/ja.json
  • src/i18n/locales/ko.json
  • src/i18n/locales/pt-BR.json
  • src/i18n/locales/ru.json
  • src/i18n/locales/tl.json
  • src/i18n/locales/zh.json
  • src/pages/Editor.tsx
  • src/utils/environment.ts
  • src/utils/queryGuard.ts
  • tests/contexts/ProductionGuardContext.test.tsx
  • tests/contexts/SettingsProvider.test.tsx
  • tests/hooks/useDangerousQueryGuard.test.ts
  • tests/hooks/useQueryGuards.test.ts
  • tests/utils/environment.test.ts
  • tests/utils/queryGuard.test.ts
Previous Review Summary (commit 42e9431)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 42e9431)

Status: No Issues Found | Recommendation: Merge

The PR unifies safety-confirmation guards by running the production-write guard before the standard dangerous-query guard across editor, batch, notebook, and AI-generated query paths, gates the 5-second confirmation countdown behind a persisted safetyConfirmationDelayEnabled setting (default off), and suppresses the dangerous-query modal on production connections.

Verification highlights:

  • Guard ordering is correct in passQueryGuards (production first, short-circuits on block) and wired into runQuery, runMultipleQueries, runCell, and the AI onInsert handler.
  • No coverage gap from disabling the dangerous-query guard on production connections: isReadOnlyQuery returns false for DROP/TRUNCATE/DELETE/UPDATE, so the production guard is a strict superset and still prompts for every non-read-only write.
  • No stale closures: guardDangerousQuery/guardProductionWrite are included in the useCallback dependency arrays of runQuery (Editor.tsx:1170-1171), runMultipleQueries (1373-1374), and runCell (NotebookView.tsx:446-447).
  • Countdown timer in ProductionGuardContext decrements correctly (5→0 over 5 ticks), resets on finish, and keeps cancel/X enabled throughout.
  • confirmDelaySeconds={undefined} is safe — ConfirmModal treats the prop as optional (?? 0, !confirmDelaySeconds guard).
  • Config persistence in config.rs follows the established is_some() merge pattern; serde camelCase round-trip is covered by tests.
  • i18n: both safetyConfirmationDelay and safetyConfirmationDelayDesc keys are present in all 11 locales; zh.json also fixes a missing trailing comma.
  • Tests cover guard ordering, countdown behavior, environment detection, the disabled-guard path, and settings persistence.
Files Reviewed (25 files)
  • src-tauri/src/config.rs
  • src/components/notebook/NotebookView.tsx
  • src/components/settings/GeneralTab.tsx
  • src/contexts/ProductionGuardContext.tsx
  • src/contexts/SettingsContext.ts
  • src/hooks/useDangerousQueryGuard.ts
  • src/i18n/locales/de.json
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/it.json
  • src/i18n/locales/ja.json
  • src/i18n/locales/ko.json
  • src/i18n/locales/pt-BR.json
  • src/i18n/locales/ru.json
  • src/i18n/locales/tl.json
  • src/i18n/locales/zh.json
  • src/pages/Editor.tsx
  • src/utils/environment.ts
  • src/utils/queryGuard.ts
  • tests/contexts/ProductionGuardContext.test.tsx
  • tests/contexts/SettingsProvider.test.tsx
  • tests/hooks/useDangerousQueryGuard.test.ts
  • tests/utils/environment.test.ts
  • tests/utils/queryGuard.test.ts

Reviewed by glm-5.2 · Input: 42.3K · Output: 14.1K · Cached: 376.7K

@debba
debba merged commit 041fa3d into main Aug 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant