feat(categories): restore backup banner and permanent restore action (#122) #132
No reviewers
Labels
No labels
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#132
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-122-restore-backup-banner"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Fixes #122.
Surfaces the automatic pre-migration SREF backup to the user so a category migration can be rolled back without digging into the filesystem.
On success:
categories_schema_version=v2+ mergereverted_atintolast_categories_migration.Files
src/components/settings/CategoriesMigrationBackupBanner.tsx,CategoriesMigrationRestoreModal.tsx.src/services/categoryRestoreService.tswrappingread_import_file+importTransactionsWithCategorieswith stable error codes.src/services/categoryRestoreService.test.tsforshouldShowBanner/isWithinBannerWindow.file_existsinsrc-tauri/src/commands/backup_commands.rs.CategoriesCard.tsxto mount the banner + permanent restore entry.settings.categoriesCard.restore*.Test plan
npx tsc --noEmit— cleannpx vitest run— 193 tests pass (12 new)npm run build— cleancargo check— cleancargo test --lib— 34 passedv2and data matches pre-migration stateSelf-review
Security (destructive action)
bg-[var(--negative)]) and the warning text is visible on every phase.phase === "restoring". A user cannot accidentally close the modal mid-wipe.is_file_encryptedreturns true, the flow branches to a password prompt. The Restore CTA there is disabled while the field is empty. Wrong PIN surfaceswrong_password(i18n-mapped) and lets the user retry without re-opening the modal.file_existsis checked before callingread_import_file, flipping to themissingphase and offering a file picker. No crash, no ambiguous error.importTransactionsWithCategories), no migration SQL touched, no DB schema change.Pre-existing residual risk (out of scope)
importTransactionsWithCategoriesperformsDELETE … ; INSERT …outside aBEGIN/COMMITblock. A failure mid-import would leave the profile partially wiped. This predates #122 and the risk is identical to the existing Settings → Import data flow. Worth tracking in a follow-up issue but not in this PR.i18n
settings.categoriesCard.restoreBanner.*,settings.categoriesCard.restoreEntry.*,settings.categoriesCard.restoreModal.*— present in bothen.jsonandfr.json. Error codes mapped 1:1 fromRestoreError.Intl.NumberFormat/toLocaleStringused for dates (matches user locale).Changelog
CHANGELOG.mdandCHANGELOG.fr.mdunder## [Unreleased] / ### Added, detailing banner + permanent entry + new Tauri command + new service.Tests
shouldShowBanner/isWithinBannerWindow(pure functions). Covers: no migration, recent/expired, dismissed, reverted, boundary at 90d, invalid timestamp, custom window, non-"1" dismissal values.cargo test --lib34 tests pass.CI signals
npx tsc --noEmitclean.npm run buildclean.cargo checkclean.LGTM by myself.