85da2e538d
Auto-backups now produce a ZIP containing ledgrab.db plus every file in the assets dir under assets/ — matching the manual GET /api/v1/system/backup format, so restore accepts either output interchangeably. Legacy .db backups remain listable, restorable, and prunable; both extensions count toward max_backups. Writes stage to <name>.partial then os.replace into place — a crash mid-ZIP never leaves a half-written backup that masquerades as valid. Stale .partials from prior crashes are swept on the next run. Symlinks inside the assets dir are skipped so a hostile link can't slurp a target outside the dir into every backup. Backups larger than 500 MB log a warning so operators notice unbounded asset growth before disk fills up. restart.py: redirect the spawned restart script's stdout/stderr to restart.log and bail out early if the script is missing — silent failures (PowerShell off PATH, restart.ps1 erroring) used to vanish into a detached child with no diagnostic trail. Tests cover happy path, asset bytes round-trip, partial cleanup, None/missing assets_dir, failure rollback, stale-partial sweep, symlink rejection, mixed legacy+new listing, and cross-format prune.