9833237d37177e1d65dfd962c591788a22222ba2
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
45ffe64b7c |
fix(storage): write business documents under STORAGE_PATH, not the cwd (#1072)
Stable twin of #1070. persistDocPdf, the invoice sending and reminder writers, both contract signature writers and persistSignatureImage built their targets from `path.join(process.cwd(), 'storage', 'business-docs', ...)` and never consulted STORAGE_PATH. Both compose files pin STORAGE_PATH=/app/storage and the image's WORKDIR is /app, so on a stock deployment the two name the same directory and nothing looked wrong. Point STORAGE_PATH anywhere else and quotes, invoices, Mahnungen, contracts and signature images land outside the configured storage root: missed by the backup walker, invisible to storage accounting, and gone when the container is replaced. assertContractPdfPath moves with them. On this branch the writers and the guard are wrong together, so contract downloads currently work — migrating the writers alone would have introduced PATH_OUTSIDE_STORAGE on every newly generated contract. The guard now resolves through getStoragePath() like the writers, and keeps the legacy cwd root so contracts written before this still resolve; their absolute paths are in the database. Also on the shared resolver: the custom PDF font lookup (a font under STORAGE_PATH/fonts was never found, and the document silently fell back to the built-in face) and the two backup diagnostics, which otherwise inspect a different root than the backup walker when STORAGE_PATH is unset. No migration needed — the persisted path is stored absolute. Verified on this branch, not inferred from main: the new test is 6/6, and contract/quote/invoice/pdf/safePath suites are 213/213 both before and after the change. Claude-Session: https://claude.ai/code/session_01Ra4hcsYiKuQLbbRsg6EjAc Co-authored-by: Paul Nothaft <[email protected]> |
||
|
|
a27c705e39 |
fix(backup): make backup settings actually apply (#871) (stable) (#875)
* fix(backup): make backup settings actually apply (#871) (stable) - Wire the What-to-Backup toggles into the walker: honor backup_include_thumbnails / backup_include_photos (opt-out, default ON) and accept the UI's backup_include_archives spelling for the archived gate (the engine expected _archived, so the Archives checkbox silently never worked). - Fix the 167.6 TB dashboard size: file_size_bytes is a bigint that node-postgres returns as a string, and the S3 path concatenated it onto the byte counter; coerce to Number at the source. - Compute the real next scheduled run (cron-parser) and return it as nextBackup; the UI read a field the API never sent and rendered a hardcoded 'Not scheduled'. A named schedule label now beats the stray default cron the UI always sent, which silently turned weekly schedules into daily 03:00 runs. - Never back up filesystem noise (.nfs* silly-renames, .DS_Store, Thumbs.db) and honor backup_exclude_patterns in the walker (previously rsync-only). - Remove the compression/encryption toggles from the configuration UI: no backend implementation exists, and collecting an encryption passphrase while uploading plaintext is a false promise. * fix(backup): close the review gaps in the settings wiring (stable) - The UI's backup_include_archives now beats the migration-seeded backup_include_archived: every install has the singular key seeded true, so the alias-only-when-absent lookup made unchecking Archives a no-op. - rsync destinations now receive the de-selected What-to-Backup paths and the noise filters as anchored --exclude args; previously rsync synced the whole storage root and the walker's selection only shaped the manifest, which then misreported what was actually transferred. - Escape regex metacharacters in the walker's glob matcher: '.nfs*' compiled to /^.nfs.*$/ whose leading dot matched any character, so files like anfs-photo.jpg were silently dropped from backups. - The Backup Coverage report now uses the same gate as the walker (new 'skipped-by-setting' status) instead of re-implementing it without the opt-out toggles and the archives alias. * fix(backup): make the coverage diagnostics agree with the walker - The coverage table shows the alias-aware flag value the gate actually used, instead of the seeded backup_include_archived shadowed by the UI's plural key (true next to a 'Gated off' badge). - skipped-by-setting paths are now counted in the coverage summary (backend, TS contract, summary card, EN/DE locales) so the totals reconcile again when Photos or Thumbnails is unchecked. - The form's thumbnail default now matches the backend's never-saved fallback (include): the checkbox no longer shows 'off' while thumbnails are being backed up, and saving an unrelated setting no longer flips the backup scope. (stable) * fix(backup): keep custom crons, exclude disabled rows from rsync, normalize flag display - Saving a named schedule no longer wipes the stored custom cron: the backend already prefers the label, so the cron field stays inert for named schedules and is preserved for switching back to Custom. A custom schedule now validates the 5-field expression before saving (the backend silently fell back to daily 02:00 on a blank value). - resolveExcludedBackupPaths now also returns rows disabled via include_in_default, so rsync excludes them; the enabled-only loader hid them and rsync transferred their contents anyway. - The coverage table normalizes flag values like the walker does — Boolean('false') displayed true beside a gated-off badge. (stable) |
||
|
|
03e6617f38 |
feat(backup): coverage diagnostic — what will the next backup miss?
Stage C of the three-stage backup-hardening plan (Stage A: inline
DB dump + fail-loud landed in 7fdf01a; Stage B: config-driven walker
in
|