- storage.py: atomic save_json (temp+fsync+os.replace) and load_json that
survives missing/corrupt files (moves corrupt aside). Closes #11/#12.
- route all data modules + app.py helpers through storage (closes#31 core);
fixes mutable DEFAULT_FUNDS/DEFAULT_CARS return (#23).
- gunicorn --workers 1 --threads 4 to remove the write race (#13); strip
Dockerfile template scaffolding (#40).
- base.html: 💡 suggestions link in the shared nav (shows on every page).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- backup.sh: snapshot all of /data as timestamped tar.gz to local NAS path;
push to B2 only when a real bucket/key is set (no more nonexistent app.db).
- compose: working CMD-SHELL healthcheck; mount /mnt/user/Backup target.
- remove the accidentally committed moon-household-budget-handoff/ scaffolding.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>