Add backup/restore, daily auto-backup and history CSV/JSON export (Phase E3)
- create_backup writes a zip (manifest with sha256 per file, a VACUUM INTO database snapshot, assets, archive, fonts) atomically. restore_backup validates the manifest, rejects tampered files, path traversal, symlinks and newer schemas, checks the staged DB with integrity_check, then stages a pending restore. The swap runs on the next start before the database opens, moves the current data to backups/pre-restore-<ts>/ and rolls back on any failure. - Daily automatic backup (migration M9 auto_backup, default on) keeps the newest 14 and never blocks startup. - Settings Data tab: back up now, restore with confirmation and restart, auto-backup toggle, last backup time. - History exports the filtered rows as CSV (UTF-8 BOM, CRLF, formula-injection guard) or JSON (voiced.history.v1) with CA-friendly tax columns from a new list_invoice_ledger command. - Rust round-trip, rejection, swap-rollback and retention tests; vitest for the export and backup helpers. Adds the zip 8.6.0 and typed-path 0.12.3 crates (pure Rust); package builds must vendor them. PDF output and fingerprint goldens are unchanged. The new UI has not been run in a webview yet.
This commit is contained in:
@@ -541,6 +541,26 @@ body {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* ---------- Settings: Data tab ---------- */
|
||||
.voiced-section-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.voiced-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.voiced-list {
|
||||
margin-left: 1.25rem;
|
||||
list-style: disc;
|
||||
}
|
||||
|
||||
/* ---------- Invoice history and detail ---------- */
|
||||
.voiced-num {
|
||||
text-align: right;
|
||||
@@ -578,6 +598,14 @@ body {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.voiced-history__export {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.voiced-history__row {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user