- settings.py: JSON-on-volume store with env fallback; secrets never rendered.
- /settings page (⚙️ in nav) to set Gmail address + app password + reminder prefs;
password fields are write-only (blank keeps existing).
- reminders.py reads Gmail creds from Settings instead of a hardcoded password
(resolves#2 in code — note the old password is still in git history; rotate it).
- mac_notification no longer crashes off-macOS; FLASK_DEBUG gates debug (#7).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>