feat(categories): categoryBackupService pre-migration SREF wrapper (#120) #124

Merged
maximus merged 1 commit from issue-120-category-backup-service into main 2026-04-19 20:48:52 +00:00
Owner

Fixes #120

Livraison 2 — filet de sécurité obligatoire avant la migration v2→v1.

  • Nouveau service src/services/categoryBackupService.ts
  • Génère + vérifie un backup SREF complet (write → read back → SHA-256 compare)
  • Nom de fichier: <ProfileName>_avant-migration-<ISO8601>.sref (sanitisé, :- pour Windows)
  • Emplacement: ~/Documents/Simpl-Resultat/backups/ (créé si manquant)
  • Erreurs stables (BackupError avec codes) — à mapper en clés i18n côté UI
  • Réutilise le PIN du profil pour chiffrement quand protégé
  • Deux commandes Tauri minimales ajoutées: ensure_backup_dir, get_file_size
  • Prêt à être consommé par #121 (page migration)

Build + type-check + tests existants (133 vitest + 34 cargo) passent.

Fixes #120 Livraison 2 — filet de sécurité obligatoire avant la migration v2→v1. - Nouveau service `src/services/categoryBackupService.ts` - Génère + vérifie un backup SREF complet (write → read back → SHA-256 compare) - Nom de fichier: `<ProfileName>_avant-migration-<ISO8601>.sref` (sanitisé, `:` → `-` pour Windows) - Emplacement: `~/Documents/Simpl-Resultat/backups/` (créé si manquant) - Erreurs stables (`BackupError` avec codes) — à mapper en clés i18n côté UI - Réutilise le PIN du profil pour chiffrement quand protégé - Deux commandes Tauri minimales ajoutées: `ensure_backup_dir`, `get_file_size` - Prêt à être consommé par #121 (page migration) Build + type-check + tests existants (133 vitest + 34 cargo) passent.
maximus added 1 commit 2026-04-19 19:46:42 +00:00
feat(categories): add categoryBackupService for pre-migration SREF backup (#120)
All checks were successful
PR Check / rust (push) Successful in 22m20s
PR Check / frontend (push) Successful in 2m18s
PR Check / rust (pull_request) Successful in 22m1s
PR Check / frontend (pull_request) Successful in 2m16s
3c628d4cd1
Wrapper around dataExportService that creates and verifies a full SREF
backup before the v2->v1 categories migration. Throws on any failure to
ensure migration aborts cleanly.

- Generates filename <ProfileName>_avant-migration-<ISO8601>.sref
- Writes to ~/Documents/Simpl-Resultat/backups/ (creates dir if missing)
- Verifies integrity via re-read + SHA-256 checksum
- Reuses profile PIN for encryption when protected
- Adds two minimal Tauri commands: ensure_backup_dir, get_file_size
- Stable error codes (BackupError) to map to i18n keys in the UI layer

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author
Owner

Review verdict: APPROVE

Security

  • SHA-256 computed on decrypted JSON roundtrip (Web Crypto crypto.subtle.digest) — validates logical integrity end-to-end including encryption/decryption.
  • Password never echoed in logs or error messages. Explicitly dropped from BackupError.detail.
  • Path traversal safe: sanitizeProfileName strips \/:*?"<>| + control chars + trailing dots, collapses whitespace, caps at 80 chars, falls back to "profile" for empty/./.. inputs. The filename is joined to a trusted directory path so traversal cannot escape the backups dir.
  • ISO8601 made filesystem-safe for Windows (:-, fractional seconds removed).

Correctness

  • Verification step actually re-reads the file via read_import_file (which decrypts if needed), re-parses the envelope, and compares SHA-256 of both payloads.
  • All error paths throw BackupError with stable code + detail — nothing swallowed.
  • PIN-protected profile without password → throws missing_password before any write.
  • Unencrypted profile with empty password → correctly passes null (won't trigger encryption path in write_export_file).
  • write_export_file errors mapped to stable codes (disk_space, permission_denied, write_failed).

Quality

  • Strict TypeScript, no any.
  • Error codes are intentionally stable English identifiers for i18n mapping — not user-facing strings.
  • Dead-code free. Small, focused service (~320 lines, heavily commented).
  • Two minimal new Tauri commands (ensure_backup_dir, get_file_size) — no modification of existing commands.

Data

  • Service does not touch the DB (only reads via existing dataExportService helpers).
  • Does not modify existing services or commands.

Build / Tests

  • cargo check
  • cargo test → 34 passed ✓
  • npm run build (tsc + vite) ✓
  • npm test → 133 passed ✓

Ready to be consumed by #121 (migration page).

## Review verdict: APPROVE ### Security - SHA-256 computed on decrypted JSON roundtrip (Web Crypto `crypto.subtle.digest`) — validates logical integrity end-to-end including encryption/decryption. - Password never echoed in logs or error messages. Explicitly dropped from `BackupError.detail`. - Path traversal safe: `sanitizeProfileName` strips `\/:*?"<>|` + control chars + trailing dots, collapses whitespace, caps at 80 chars, falls back to `"profile"` for empty/`.`/`..` inputs. The filename is joined to a trusted directory path so traversal cannot escape the backups dir. - ISO8601 made filesystem-safe for Windows (`:` → `-`, fractional seconds removed). ### Correctness - Verification step actually re-reads the file via `read_import_file` (which decrypts if needed), re-parses the envelope, and compares SHA-256 of both payloads. - All error paths `throw BackupError` with stable `code` + detail — nothing swallowed. - PIN-protected profile without password → throws `missing_password` before any write. - Unencrypted profile with empty password → correctly passes `null` (won't trigger encryption path in `write_export_file`). - `write_export_file` errors mapped to stable codes (`disk_space`, `permission_denied`, `write_failed`). ### Quality - Strict TypeScript, no `any`. - Error codes are intentionally stable English identifiers for i18n mapping — not user-facing strings. - Dead-code free. Small, focused service (~320 lines, heavily commented). - Two minimal new Tauri commands (`ensure_backup_dir`, `get_file_size`) — no modification of existing commands. ### Data - Service does not touch the DB (only reads via existing `dataExportService` helpers). - Does not modify existing services or commands. ### Build / Tests - `cargo check` ✓ - `cargo test` → 34 passed ✓ - `npm run build` (tsc + vite) ✓ - `npm test` → 133 passed ✓ Ready to be consumed by #121 (migration page).
maximus merged commit 63feebefc8 into main 2026-04-19 20:48:52 +00:00
maximus deleted branch issue-120-category-backup-service 2026-04-19 20:48:52 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#124
No description provided.