Repository navigation
fix(main): preserve local backup opt-out and retention across resets and restores - #1331
Merged
Merged
Conversation
Contributor
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Verify and fix release-audit finding F3 (P2, data safety / privacy) in the daily local backup feature (#1303, #1329):
When an owner disables automatic daily local backups (
local_backup_enabled = 'false'), that opt-out is currently wiped and silently re-enabled (true) by:POST /api/db-tools/currency-reset->resetDatabaseForCurrencyChangeinmain/db.ts), which preserves only['country', 'currency', 'timezone'], deleteslocal_backup_enabled = 'false', and re-inserts the store's products so the nextlocalBackup.runIfDue()writes a.dbbackup toDocuments/FloCafe/Backupsdespite the opt-out; conversely, whenlocal_backup_enabledis enabled (true),POST /api/db-tools/currency-reset(main/routes/database-tools.ts) does not callretainBackupLocally(result.backupPath)likePOST /api/db-tools/initializedoes.db-initialize(main/ipc.ts), which callsresetDatabaseWithBackup()without preservinglocal_backup_enabled = 'false'and without callingretainBackupLocally(backupPath)when enabled.restoreBackup/RESTORE_PROTECTED_SETTING_KEYSinmain/db.ts), which does not include'local_backup_enabled'inRESTORE_PROTECTED_SETTING_KEYS, so restoring an older backup overwriteslocal_backup_enabled = 'false'back to'true'(or deletes the row, which defaults totrue).What Changed
local_backup_enabledacrossresetDatabaseWithBackupUnlockedandresetDatabaseForCurrencyChangeinmain/db.ts, and include'local_backup_enabled'inRESTORE_PROTECTED_SETTING_KEYSso both direct and data-onlyrestoreBackupruns retain the active setting.retainBackupLocallywhen local backups are enabled (or keepsetLocalBackupEnabled(false)when disabled) and returnlocalBackupFailedfromPOST /api/db-tools/currency-reset(main/routes/database-tools.ts) and thedb-initializeIPC handler (main/ipc.ts).docs/architecture/data-and-migrations.mdanddocs/reference/api.md, and add regression tests intests/local-backup.test.ts.Risk Assessment
✅ Low: The change is well-bounded and directly preserves the local_backup_enabled setting and pre-reset local backup retention across database resets, currency resets, and backup restores with comprehensive behavioral test coverage.
Testing
Ran the focused local-backup, database-tools-api, currency, and backup test suites, and stood up the live Express API server, IPC handlers, SQLite database, and LocalBackupService in an isolated disposable environment to drive currency reset (opted-out, enabled, and obstructed backup directory), Electron IPC db-initialize (opted-out and enabled), and HTTP backup restore (direct with enabled setting, direct with missing setting row, and data-only from an older schema) with recorded evidence; all checks passed. This is a backend persistence and IPC/API contract change with no UI/visual surface change.
Evidence: Live API, IPC, SQLite, and local backup directory verification transcript
{ "currencyResetOptedOut": { "currencyResetResponse": { "status": 200, "data": { "success": true, "currency": "EUR", "localBackupFailed": false } }, "getLocalBackupAfterReset": { "status": 200, "data": { "enabled": false } }, "dbSettingRowAfterReset": { "key": "local_backup_enabled", "value": "false" }, "survivingProductCount": 1, "localBackupsAfterRunIfDue": [] }, "currencyResetEnabled": { "currencyResetResponse": { "status": 200, "data": { "success": true, "currency": "GBP", "localBackupFailed": false } }, "dbSettingRowAfterReset": { "key": "local_backup_enabled", "value": "true" }, "retainedLocalBackups": ["flo-backup-2026-10-23T16-42-35-838Z.db"] }, "currencyResetObstructedBackupDir": { "currencyResetResponse": { "status": 200, "data": { "success": true, "currency": "CAD", "localBackupFailed": true } } }, "ipcDbInitialize": { "ipcDisabledResult": { "success": true, "localBackupFailed": false }, "getLocalBackupAfterIpcDisabled": { "status": 200, "data": { "enabled": false } }, "localBackupsAfterIpcDisabledRunIfDue": [], "ipcEnabledResult": { "success": true, "localBackupFailed": false }, "retainedLocalBackupsAfterIpcEnabled": ["flo-backup-2026-10-23T16-42-36-748Z.db"] }, "backupRestoreOptedOut": { "directRestoreEnabledSnapshot": { "restoreResponse": { "status": 200, "data": { "mode": "direct" } }, "getLocalBackupAfterRestore": { "data": { "enabled": false } } }, "directRestoreMissingRowSnapshot": { "restoreResponse": { "status": 200, "data": { "mode": "direct" } }, "getLocalBackupAfterRestore": { "data": { "enabled": false } } }, "dataOnlyRestoreOlderSnapshot": { "restoreResponse": { "status": 200, "data": { "mode": "data_only" } }, "getLocalBackupAfterRestore": { "data": { "enabled": false } } }, "dbSettingRowAfterAllRestores": { "key": "local_backup_enabled", "value": "false" }, "localBackupsAfterRunIfDue": [] } }Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
npm run test:local-backupnpm run test:database-tools-apinpm run test:currencynpm run test:backupnode tests/run-electron-node-test.cjs -e '<live server + IPC + SQLite + localBackup scenario verification>'✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.