• v1.1.0 1a7ef09805

    kraehed released this 2026-05-25 20:46:30 +00:00 | 0 commits to main since this release

    [1.1.0] - 2026-05-19

    Added

    • Auth — Email verification: SHA-256 token (24h TTL) sent on registration; /verify-email?token= route auto-confirms via POST /api/auth/verify-email/
    • Auth — Password reset: anti-enumeration POST /api/auth/password-reset/; confirm endpoint resets password and invalidates all sessions; SHA-256 token with 15 min TTL sent via Brevo
    • Auth — 2FA (TOTP): QR code setup, HMAC-signed 5 min temp token, replay protection via totp_last_used_code, 8 backup codes (SHA-256 hashed in DB, XXXXXXXX-XXXXXXXX format); copy to clipboard + PDF download via jsPDF; two-step login flow
    • Auth — "Keep me signed in": toggles between localStorage (persistent) and sessionStorage; carried through 2FA and recovery flows
    • Auth — Language switcher (LangSwitcher): embedded in login and register cards
    • Settings page (/settings): active sessions (list all devices, individual revoke, revoke-all); data export (ZIP with 6 structured PDFs via fpdf2); notification preferences (deadlines, budget warnings, monthly summary); 2FA management; three-step account deletion (mandatory export → password + confirmation phrase → redirect to armarium.ch)
    • Dashboard: income vs. expenses bar chart (3 series, year selector); fixed costs donut chart with toggle to scrollable list view; savings rate card with customisable target marker
    • Security: Cloudflare Turnstile CAPTCHA on login and register
    • Infrastructure: Brevo SMTP (smtp-relay.brevo.com:587), domain armarium.ch verified (SPF/DKIM); all email config via env vars (EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, etc.)
    • Email templates: registration_confirm, password_reset, password_changed, email_changed — HTML + plaintext; finance/email.py generic helper using EmailMultiAlternatives
    • Backend: ADMIN_URL env var obscures the admin path (default manage/); production security block — SECURE_SSL_REDIRECT, HSTS (1 year, preload, subdomains), secure cookies, SECURE_CONTENT_TYPE_NOSNIFF; upload size capped at 5 MB; CSRF_TRUSTED_ORIGINS from env var
    • i18n: all new keys for financial year, household, dashboard, auth flows, settings and 2FA (DE/EN/FR/IT)

    Changed

    • Login: email-based authentication (username removed, backend auto-sets username=email); "Forgot password?" link; two-step flow when 2FA is active; show/hide password toggle; font sizes increased throughout login/register cards
    • Register: email-only; independent show/hide toggle on both password fields; display-name hint
    • Dashboard: KPI data now sourced from FinancialYearService (was account/budget totals)
    • Settings: 2FA and active sessions moved here from Profile; account deletion is now three-step
    • Calendar: live holiday and school holiday data via OpenHolidays API (AGPL-3.0) with static fallback; language-aware requests and cache key; in-memory cache per year/canton; today shown as violet ring only (not filled)
    • Notifications: per-notification "mark as read" button; "mark all as read" in panel header
    • Typography: Roboto self-hosted via @fontsource/roboto (300/400/500/700) — no Google Fonts CDN, GDPR-compliant; unified font-size scale with custom Tailwind steps
    • Mobile: responsive improvements across tables (hidden columns), modals (single-column grids), touch targets (min p-2), dashboard KPI cards, calendar cells, OTP inputs, notification panel margins; sidebar mobile drawer now contains notifications, theme toggle, profile and logout
    • Backend: LogoutView accepts unauthenticated calls and deletes UserSession by JTI; ChangePasswordView invalidates all other sessions; authInterceptor sends X-Session-Key header on every request; session key stored alongside JWT in same storage

    Security

    • Password reset invalidates all active sessions
    • Email verification token stored as SHA-256 hash with 24h TTL
    • VerifyEmailView and PasswordResetConfirmView rate-limited at 5/min
    • TwoFactorRecoverConfirmView: temp_token verified before accepting a recovery code (previously bypassable)
    • ProfileView.delete: requires password verification; returns 403 on failure

    Fixed

    • EmailAuthBackend: case-insensitive email lookup so login works regardless of capitalisation
    • Dashboard: December bars no longer clipped at the right edge of the bar chart
    • Calendar: legend removed from footer; ZH spring holidays 2026 corrected to 20.04.–02.05.; date input locale bound to app language; deadline type dropdown shows placeholder on open; placeholder text styled correctly
    • Auth LangSwitcher: signal initialisation order fixed; [class] binding used instead of [class.dark:...] to avoid Tailwind dark-mode colon conflict
    • Backend: fpdf2 export — em/en dash caused FPDFUnicodeEncodingException with Helvetica; fixed via Latin-1 safe encoding helper
    • Backend: api/notifications/ URL conflict resolved; prefs endpoint moved to api/notifications/prefs/
    • Mobile navbar: icons hidden on mobile and integrated into sidebar drawer to prevent layout overflow
    Downloads