# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [0.96.11] - 2026-07-07 ### Fixed - **Papra/Paperless DMS documents did not appear until an exact search term was typed** — the "Link from DMS" dialog required a non-empty query, and an empty query was rejected at the adapter, route, and frontend layers, so a correctly configured DMS looked empty. The dialog now lists all documents from the connected DMS on open (empty query), and clearing the search field lists everything again. Both Papra (`searchQuery` omitted) and Paperless-ngx (`query` omitted) natively return the full document list in that case (#449). ## [0.96.10] - 2026-07-06 ### Fixed - **Split expenses could not be edited after adding them** — expense rows under Budget → Split were a static, non-interactive list. Each row is now a button that opens the expense dialog in edit mode (pre-filled with title, amount, payer, currency, date, split method, participants, and per-participant split values), with a delete action. The `PUT`/`DELETE /expenses/:id` routes already existed; only the frontend wiring was missing (#445). ## [0.96.9] - 2026-07-06 ### Fixed - **Split balances reset after archiving a group** — the "You owe" / "You are owed" totals under Budget → Split now exclude archived groups. The dashboard balance query was missing an active-status filter, so an archived group's ledger entries kept inflating the totals, and archiving/deleting a group did not refresh the summary (#446). ## [0.96.8] - 2026-07-05 ### Fixed - **Living background no longer burns the GPU** — the animated backdrop blobs (`.lg-backdrop`) now drift with a translate-only animation on their own compositor layer instead of also scaling, which forced the 90px blur to re-rasterise every frame. Idle pages drop from 25–50% continuous GPU usage to negligible compositing, while the drift effect is preserved (#443). ## [0.96.7] - 2026-07-05 ### Changed - **Calmer sidebar section labels (desktop)** — the navigation group headings ("Overview", "Plan", "Home") now use sentence case instead of small tracked uppercase, so they read more clearly and match the warm family-planner tone. - **Collapsed sidebar reveals labels on demand (desktop)** — hovering or keyboard-focusing the collapsed icon rail now expands it to show the labels, so items stay identifiable without permanently widening the sidebar. - **Sidebar highlight follows keyboard focus (desktop)** — the sliding active-item indicator now previews on keyboard focus, not only on mouse hover. ### Fixed - **Sidebar focus outline no longer clipped (desktop)** — the keyboard focus ring on navigation items and the collapse toggle now sits inside the sidebar edge instead of being cut off. - **Settings stays pinned to the bottom of the sidebar (desktop)** — pinning uses an explicit marker, so a custom module rendered last can no longer push Settings out of place. ## [0.96.6] - 2026-07-05 ### Changed - **Clearer "More" navigation icon (mobile)** — the bottom-bar overflow tab now uses a horizontal-ellipsis glyph that reads unambiguously as "more", replacing the previous grid-of-dots icon. - **Larger mobile navigation touch targets** — the bottom bar and its icon buttons are taller, making one-handed taps more comfortable and reducing mis-taps. - **Kitchen tab announces its destination** — screen-reader and keyboard users now hear which section (Meals, Recipes, or Shopping) the Kitchen tab will open, even before it becomes active. ### Fixed - **Navigation labels no longer clip in longer languages** — mobile bottom-bar labels wrap to two lines instead of truncating (e.g. longer German and French module names). - **"More" sheet respects reduced motion** — the mobile "More" sheet and its full-screen search overlay now fade in place instead of sliding up when the system "reduce motion" preference is enabled. ## [0.96.5] - 2026-07-05 ### Fixed - **Italian translation** — UI strings across tasks, meals, calendar, settings, API tokens, CalDAV/CardDAV, backups, and housekeeping that were still showing English (or German) placeholders are now fully translated. ## [0.96.4] - 2026-07-05 ### Added - **Time-of-day greeting on the dashboard** — the personal greeting now carries a warm gradient that shifts with the time of day (sunrise orange in the morning, deep amber at midday, violet in the evening), with solid-color fallbacks when reduced transparency or higher contrast is preferred. - **Auto-hiding quick-action button** — the floating "+" button on the dashboard slides out of the way as you scroll down and returns when you scroll up, so it no longer covers a widget's "All" shortcut on small screens. ### Changed - **Per-widget error handling on the dashboard** — if a single widget's data fails to load, only that widget shows an inline error with a "Retry" button; the rest of the dashboard stays usable instead of failing as a whole. - **Custom widget order is preserved** — a dashboard you have re-ordered yourself is no longer re-packed automatically, while the default layout still packs tightly to avoid empty gaps on wide screens. - **Simpler widget sizes** — the widget size picker now offers four clear presets; layouts using older sizes are mapped to the nearest one. ### Fixed - **Budget widget footer** — no longer shows a misleading "no budget data" message when budget data exists but no top spending category is available. ## [0.96.3] - 2026-07-05 ### Fixed - **Duplicate holidays that survived a resync** — the calendar now de-duplicates holidays when reading them, so identical public or school holidays never appear twice even if leftover cache rows from a previously selected region remain from before the v0.96.1 fix. Affected users no longer need a perfect re-sync to clear old duplicates. ## [0.96.2] - 2026-07-05 ### Fixed - **Paperless-ngx DMS connection failing with 406** — linking and testing a Paperless-ngx account no longer fails with an "unexpected error" / HTTP 406. The adapter now negotiates the Paperless REST API with an explicit supported `Accept` version header and transparently falls back to the unversioned default for older instances that do not know that version. No extra environment variables are required. ## [0.96.1] - 2026-07-05 ### Fixed - **Duplicate holiday entries after changing region** — public and school holidays no longer appear multiple times once you switch the holiday region (e.g. from a country-wide selection to a specific state). Each holiday sync now replaces the entire cached set for that country and year, so stale entries from a previously selected scope are removed. Existing duplicates clear on the next sync (use "Sync now" in settings to trigger it immediately). ## [0.96.0] - 2026-07-05 ### Added - **Rewards dashboard widget** — a family points leaderboard showing the top participants by ledger balance, the leader subtly highlighted, plus a badge for redemptions still awaiting parental approval. - **Health dashboard widget** — today's medication doses as a "taken / total" progress bar with the next open dose and a low-stock reorder hint. Only family-visible medications are shown, so private medications never appear on a shared dashboard. - **Housekeeping dashboard widget** — a compact status showing whether the helper is currently present (with the arrival time), this month's visit count, and any outstanding payment. - Localised in all 23 languages. ### Changed - The three new widgets (Rewards, Health, Housekeeping) start hidden by default and are offered as opt-ins in Customize, so existing dashboards are not changed and fresh dashboards are not crowded with empty tiles. ## [0.95.1] - 2026-07-05 ### Fixed - **Documents toolbar restored on tablet and desktop** — the view switcher, "Add folder" button and the status, category and folder filters (including access to archived documents) were hidden and unreachable at tablet and desktop widths; they are now always visible there. ### Changed - **Denser Documents grid** — document cards size to their content instead of a fixed minimum height, tablets show two columns, and the folder browser collapses into a horizontal chip bar on tablet and mobile so the grid uses the full width. - **Cleaner document cards** — the redundant "Local" storage badge is gone (badges now appear only for external DMS/WebDAV storage) and the edit action uses a pencil icon. ## [0.95.0] - 2026-07-05 ### Added - **Tall (1×2) widget size** — a new tall-and-narrow dashboard widget size. List widgets (Tasks, Calendar) now default to it, so a short "today" list keeps useful height without taking up a full two-column row. Available in the widget size picker and localised in all 23 languages. ### Changed - **Redesigned weather widget** — an atmospheric gradient with a soft highlight and a tighter composition (temperature and icon grouped as one "now" cluster), a clearer forecast divider, and a more legible location line. White-text contrast is verified in both light and dark themes. - **Denser, calmer dashboard grid** — widgets no longer stretch to fill empty cells (short lists stay compact instead of becoming half-empty cards), small widgets backfill the gaps left by wide ones, and the "Today" cockpit adapts its column count to the number of cards shown. - **No duplicate "Today" entries** — when a module's own widget is visible on the dashboard, the matching "Today" cockpit card is now hidden, so each domain is represented once instead of twice. - **Refined "Today" cockpit cards** — the summary cards are de-framed into tinted zones rather than cards nested inside a card. ### Fixed - **Weather forecast now visible on mobile** — the multi-day forecast stays in the narrow mobile weather widget instead of being hidden, so the widget shows real information rather than empty space. - **Task priority no longer relies on colour alone** — priority markers now also differ in size and shape (filled vs. outlined), meeting WCAG 1.4.1 for colour-blind users; the screen-reader priority label is unchanged. ## [0.94.2] - 2026-07-04 ### Changed - **Faster module switching** — page modules and their stylesheets are now prefetched the instant you hover or touch a navigation item, and the main modules are warmed during idle time after the app loads. Selecting a module from the menu no longer waits on a cold load, so the transition feels immediate instead of sluggish. - **Instant navigation feedback** — the active navigation highlight, indicator pill, and module accent colour now update the moment you tap a menu item, rather than only after the target module has finished loading. ## [0.94.1] - 2026-07-04 ### Changed - **Unified tab styling across modules** — the Budget tab bar (Budget/Subscriptions/Loans/Statistics/Split) and the Shopping list switcher now share the same pill-shaped active state (a subtle tinted highlight in each domain's own colour) used by the rest of the app's tab surfaces, so moving between modules feels like one product. Each Budget sub-domain keeps its distinct accent colour. - **Consistent heading sizes in Subscriptions and Housekeeping** — section and card headings in these two modules now follow the app-wide typography roles instead of module-specific font-size overrides, removing the heading size jumps that appeared when navigating between modules. ## [0.94.0] - 2026-07-04 ### Added - **Keyboard navigation for tab bars** — the Rewards, Housekeeping, and Calendar (month/week/day/agenda) view switchers now support arrow keys, Home/End, roving tabindex, and full `role="tablist"` ARIA from one shared helper, so every in-page tab surface is keyboard- and screen-reader-navigable. ### Changed - **Consistent create action across modules** — the "new" action is now a single context-aware floating button (FAB) in Health, Rewards, and Housekeeping. It follows the active tab/section and respects permissions (only your own health entries; admin-only reward and bonus actions) and hides where no create action applies. Redundant inline "add" buttons were removed so the create affordance sits in one predictable place; the `n` keyboard shortcut now works wherever a FAB is shown. Subscriptions keeps Budget's existing context-aware button. - **Rewards visuals aligned with the shared design** — reward empty states now use the app-wide `.empty-state` grammar, and the points progress bar animates via transform (the same convention as the Budget, Dashboard, and Tasks bars) instead of a module-specific variant. ### Fixed - **Off-contract responsive breakpoints** — two 1px-off / non-canonical breakpoints (Tasks, Subscriptions) now follow the project's canonical breakpoint contract. ## [0.93.0] - 2026-07-04 ### Added - **Rewards module ("Belohnungen")** — a new points-and-rewards system. Tasks can now carry a point value; completing a task credits its assigned members (or the person acting on a shared kiosk tablet when no one is assigned). A household reward catalog lets members redeem points for **parent-approved** rewards, with **opt-in participation per member**, manual bonus points, and a full, auditable point ledger where every balance is the sum of its transactions. Includes a per-member standings view, an in-context first-run setup checklist for parents, keyboard/screen-reader access, and animated balance plus toast feedback. All 23 UI languages and the OpenAPI spec cover the new `/api/v1/rewards` endpoints. ## [0.92.3] - 2026-07-04 ### Added - **Login brand mark** — the login page now shows an app-tile mark with a home glyph above the wordmark, giving the sign-in screen a clear, warm identity instead of a plain text heading. ### Changed - **"Forgot password" link no longer a dead end** — the link now appears only when the server can actually deliver a reset mail (SMTP configured and `BASE_URL` set); on instances without email it is hidden entirely rather than leading to a flow that sends nothing. A new `password_reset_enabled` flag on `GET /api/v1/version` drives this. - **Login sign-in order** — the SSO button and its "or" divider now sit between the primary "Sign in" button and the "Forgot password" link, keeping the two sign-in paths together. ### Fixed - **Login page layout stability** — reserved space for the version line and only re-apply app-name branding when it actually changes, reducing layout shift on load; also improved the version text contrast. ## [0.92.2] - 2026-07-04 ### Changed - **Clearer README on catalog naming** — the README now explains that the TrueNAS and Unraid catalog listings stay registered under the legacy `oikos` slug so existing installs upgrade seamlessly, while the app itself installs and appears as Yuvomi. - **README Node requirement clarified** — the web installer's Node.js 18+ requirement is now noted as host-only; the app container ships its own Node 22. - **README polish** — unified the "See all screenshots" links and condensed the Health module row. ## [0.92.1] - 2026-07-04 ### Added - **Reveal and copy installer secret keys** — after generating the session secret or database encryption key in the setup wizard, the value is now shown and a copy button appears, with a screen-reader-announced confirmation, so the keys can be recorded before they are saved. ### Changed - **Stronger key-loss warning in the installer** — the security-keys step now leads with a prominent warning that losing the keys makes encrypted data unrecoverable, echoed by a backup reminder on the final screen. - **Grouped installer advanced step** — reverse proxy, single sign-on, backups, and WebDAV are now split into "Networking" and "Integrations & backups" sections, with the security-relevant reverse-proxy choice visually emphasized. - **Confirmation before the installer writes config** — the irreversible "Save & Start" action now asks for a second click before writing `.env` and starting the container. - **Themed visibility toggles in the installer** — show/hide controls use themed icons with pressed-state semantics instead of an emoji glyph. ### Fixed - **Correct scheme for installer redirect links** — generated Google/OIDC redirect URIs and the final "Open Yuvomi" link now use https or http based on the reverse-proxy choice instead of always using http. - **Installer accessibility and mobile polish** — the wizard now respects reduced-motion, enlarges touch targets to 44px, keeps the footer reachable on mobile, and aligns correctly in right-to-left languages. - **Safer installer input handling** — the backup cron schedule and retention count are validated, the admin step has a Back button, text fields submit on Enter, and a failed `.env` save now surfaces the actual server error. ## [0.92.0] - 2026-07-04 ### Added - **Contacts bulk selection** — an opt-in "Select" toggle in the contacts toolbar turns the list into checkboxes with select-all and batch delete (with a 5-second undo); family-linked contacts are excluded since they are managed through their member profile. - **Contacts keyboard shortcuts** — `/` focuses the search field and `n` creates a new contact (suppressed while typing in a field or while a dialog is open). - **Contacts screen-reader result count** — a live region announces the number of matching contacts as you search or filter. ### Changed - **Contact category is now a primary field** — the category selector moved out of the collapsed "advanced" section into the main add/edit form, so new contacts no longer silently default to the first category. - **Vendor-neutral contact map links** — a contact address now opens in OpenStreetMap instead of Google Maps. - **Calmer contact rows on desktop** — secondary row actions (map, export, delete) now appear on hover/focus instead of always being visible, reducing visual density. - **Clearer empty state for contacts** — searching or filtering with no matches now shows a distinct "no results" state with a reset action, separate from the first-run "no contacts yet" state. ### Fixed - **Keyboard and screen-reader access to contacts** — contact rows are now focusable buttons that open on Enter/Space instead of being click-only. - **Contacts mobile action menu no longer clipped** — the mobile "more actions" menu uses the native popover layer, so it is no longer cut off at the bottom of the list. - **No more duplicate contact dialogs or deletions** — fixed stacked click handlers that could open the edit dialog or trigger deletion multiple times after searching or filtering. - **Steadier contact list** — the list entrance animation no longer replays on every keystroke or filter change. ## [0.91.0] - 2026-07-04 ### Changed - **Calmer, more legible calendar** — event chips now use a single fill colour instead of a diagonal two-colour split for multi-person events (the people are shown as an avatar stack), and the text colour is chosen for readable contrast on every fill. - **Readable month view on phones** — the calendar month grid now shows compact event dots instead of chips squeezed down to a single letter; a "+N more" marker covers busy days, and the repeat icon no longer clutters the tiny cells. - **Consistent date entry in the calendar** — calendar event dates now use the same locale-aware date field as the task dialog and the rest of the app. - **Consistent reminder controls** — calendar event reminders now have the same on/off toggle as task reminders instead of a bare drop-down. - **Compact assignment picker** — assigning people to a task or event now uses a wrapping row of chips (tinted in the module colour) instead of a scrolling checkbox list. - **Tidier task list on mobile** — filter chips wrap onto a second row instead of being cut off at the screen edge, the redundant per-row category label is hidden (the section heading already carries it), and the floating add button no longer overlaps the last card. - **More visible task completion control** — the round complete-task control is no longer near-invisible on the dark background. ### Fixed - **Calendar header no longer shows a stale week number** — switching from the week view to month or agenda now updates the header instead of keeping the previous "KW NN" label. - **Recurrence fields hide correctly** — the repeat interval and end-date fields in the task dialog are now hidden when "no repeat" is selected. - **Correct ISO-8601 week numbers** — the calendar week number is now accurate around year boundaries. ## [0.90.0] - 2026-07-04 ### Added - **Notes now render everything the editor toolbar offers** — the sticky-note cards (and the dashboard pinboard preview) previously showed only bold and italic; any heading, list, checklist, link, code span, block quote, divider, strikethrough, or underline you added via the editor appeared as raw Markdown text on the card. Cards now render the full set: headings (`#`–`###`), ordered and unordered lists, checklists with checkboxes, block quotes, dividers, inline code, safe links, **bold**, *italic*, ~~strikethrough~~, and underline. - **Clear button in the notes search field** — a × control clears the current filter in one tap. ### Changed - **Notes editor formatting toolbar wraps on small screens** — on a phone the 13 formatting buttons no longer squeeze below finger size in the note dialog; the toolbar now wraps to a second row and the buttons keep a 44px touch target on touch devices. - **Clearer notes surface details** — the search field no longer shows a visible label that duplicated its placeholder (the label is kept for screen readers), pinned notes carry a clearer ring, and white notes get a visible edge on the warm background. ## [0.89.0] - 2026-07-04 ### Fixed - **Medication doses now show their name on mobile** — in the Health overview and Medications tab, the "Due today" rows squeezed the medication name to zero width behind the Take/Skip buttons on narrow screens, so you couldn't tell which medication a dose belonged to. The row now wraps: the name stays on its own line and the actions drop below it. - **Reloading the Health overview loads the app, not JSON** — refreshing or bookmarking `/health` returned the container health-check JSON instead of the app. Browsers (requesting HTML) now get the app; Docker and monitoring health checks still receive the JSON status as before. - **Vitals trend chart handles sparse data** — the chart no longer clusters a few readings in the middle of an empty plot: the x-axis now spans the actual data range, and periods with fewer than two readings show a clear "too few readings for a trend" hint instead of a single floating dot. Axis labels are slightly larger. ### Changed - **Consistent adherence wording** — medication adherence now uses the same term in the Overview and the Medications tab (they previously showed two different words in most languages). - **Clearer mark-as-taken action (German)** — the button now reads "Einnehmen" (an action) instead of "Genommen", which is also the taken-status label. - **Health overview uses the full width on large screens** — the overview now flows into up to three columns instead of a fixed two-column layout that left an empty right gutter. - **Themed, larger Health checkboxes** — checkboxes in Health forms now use the module accent colour and a bigger, easier-to-tap size instead of the small browser default. ## [0.88.2] - 2026-07-04 ### Fixed - **Health module is now fully translated in all 23 languages (Discussion #431)** — the Health module and its sub-tabs (Overview, Vitals, Medications, Lab results, Activity) still fell back to German for most labels, form fields, and messages in many languages, most visibly in Spanish. All 227 affected strings are now translated across the 18 languages that were incomplete (Arabic, Chinese, Czech, Dutch, French, Greek, Hindi, Hungarian, Italian, Japanese, Polish, Portuguese, Russian, Spanish, Swedish, Turkish, Ukrainian, Vietnamese); English, Korean, Indonesian, and Persian were already complete. Interpolation placeholders (dates, counts, names) are preserved in every language. ## [0.88.1] - 2026-07-03 ### Fixed - **Overview "Today at a glance" now shows the right meal (Issue #430)** — the meal card in the overview cockpit always displayed dinner, even in the morning. It now picks the meal that matches the time of day (breakfast before noon, lunch in the afternoon, dinner in the evening), with the label and icon updating to match. If the meal for the current time slot isn't planned, it falls back to the next planned meal of the day. ## [0.88.0] - 2026-07-03 ### Added - **Three new languages** — Yuvomi is now available in Korean (`ko`), Indonesian (`id`), and Persian/Farsi (`fa`), bringing the total to 23 languages. Persian renders right-to-left (RTL), like Arabic. Each language covers the full app UI as well as the web and CLI installers, and is auto-detected from the browser or shell environment. - **Three new currencies** — the budget module now supports the South Korean won (`KRW`), Indonesian rupiah (`IDR`), and Iranian rial (`IRR`). Matching region presets (`ko-KR`, `id-ID`, `fa-IR`) set currency, date, and time formats in one step. ## [0.87.0] - 2026-07-02 ### Added - **Notes & links on shopping items (Discussion #426)** — each shopping item can now carry an optional free-text note (brand, size, instructions) and an http(s) product or store link. Both are edited in a compact per-item detail drawer opened from the pencil button, so the quick-add row stays as clean as before; a subtle inline icon marks items that have extra details. Notes are included in the global search, and links open safely in a new tab (only http/https URLs are accepted). ## [0.86.0] - 2026-07-02 ### Changed - **Documents are stored more compactly (Discussion #332)** — uploaded document files and calendar attachments are now kept as raw binary (`BLOB`) inside the SQLite database instead of Base64 text. This removes the ~33 % Base64 size overhead (saving roughly 25 % of the space used by locally stored documents) and cuts CPU/RAM work on every upload and download, which is most noticeable on low-powered devices like a Raspberry Pi. Existing databases are converted automatically on first start — no manual action is required — and WebDAV/DMS-backed documents are unaffected. ## [0.85.0] - 2026-07-02 ### Added - **MCP endpoint for AI agents (Discussion #429)** — Yuvomi now serves a stateless [Model Context Protocol](https://modelcontextprotocol.io) endpoint at `/mcp` (JSON-RPC 2.0 over HTTP). AI clients such as Claude Desktop can list and create tasks, shopping items, and calendar events through natural language. It authenticates with the existing API tokens (`Authorization: Bearer `), so no new environment variable, port, or setup step is required. ## [0.84.0] - 2026-07-02 ### Added - **Calendar event colors now sync per event (Discussion #427)** — Google Calendar event colors are shown in Yuvomi, and per-event colors are also read from CalDAV, Apple, and ICS calendars (iCalendar `COLOR`, RFC 7986); an event without its own color still inherits its calendar's color. When a local event is pushed out to Google, its color is mapped to the nearest of Google's event colors. ### Fixed - **CalDAV and Apple syncs no longer discard an event color you set in Yuvomi** — previously every resync overwrote it with the calendar color. A resync now only updates the color of events you haven't recolored yourself, matching how Google and ICS calendars already behaved. ## [0.83.1] - 2026-07-02 ### Added - **ZAR (South African Rand)** added to the currency list — Budget subscriptions, split expenses, and household base currency now accept ZAR alongside the existing currencies. ## [0.83.0] - 2026-07-01 ### Added - **New Health module** (`/health`) — a private, per-member health tracker with five tabs: Overview, Vitals, Medications, Lab results, and Activity. Every entry belongs to a family member with `private`/`family` visibility, and the whole module can be disabled like any other. - **Vitals** — record blood pressure (systolic/diastolic/pulse), glucose, weight, SpO₂ and temperature, with per-metric cards showing the latest value and a native SVG trend chart (week/month/year) plus a screen-reader data table. - **Medications** — medication list with dosage, form and active/as-needed flags, a schedule editor (times + weekday mask + dose), a "due today" list with taken/skipped logging, a 7-day adherence rate, and stock/refill warnings. Dose reminders are delivered through the existing push and notification channels. - **Lab results** — structured reports with multiple analytes, reference ranges, automatic low/normal/high flags, and a per-analyte trend chart with a shaded reference band. - **Activity** — training log (type preset or free text, duration, distance, intensity, calories) with a weekly summary and a native SVG bar chart. - **Overview** — today's due doses with inline take/skip, adherence rate and streak, latest-vitals cards, upcoming reminders, quick-capture shortcuts, and CSV export per area over any date range. - **Health entries in global search** — medications and activities are indexed and deep-link back to their tab. - **Medical disclaimer** in the overview and capture modals — Yuvomi is for personal record-keeping only and makes no diagnostic claims. Health data is sensitive; database encryption (`DB_ENCRYPTION_KEY`, SQLCipher) is recommended. ## [0.82.0] - 2026-07-01 ### Added - **Dashboard load errors now show a clear, retryable message** — a failed load renders a distinct error state with a Retry button (with different wording for a dropped connection, an expired session, or a server problem) instead of empty widgets that looked like a calm day. - **Empty Shopping and Budget widgets offer a "+ Create" shortcut** into the module, so a fresh household isn't left at a dead end. - **Dashboard widgets can be reordered by keyboard and on touch** — arrow keys move a focused widget in edit mode, and touch devices get Up/Down buttons (mouse drag still works on desktop). - **Hiding every widget now shows a "re-enable via Customize" hint** instead of a blank grid. ### Changed - **The dashboard now leads with the Today Cockpit as its single overview** — the Tasks, Calendar, Shopping, and Meals widgets start hidden because the cockpit already summarizes them, so the first screen orients instead of overwhelming. A one-time hint points to Customize, and existing saved layouts are untouched. - **The Budget widget was redesigned** to lead with the monthly balance, one highlighted savings rate, and a quiet income/expenses line instead of four equal-weight metric boxes. - **Weather is no longer the first widget** in the default layout. - **Larger touch targets** on dashboard list rows and the edit-mode controls for easier tapping on phones. - **Resetting the dashboard layout now asks for confirmation** before discarding your arrangement. - **The Customize dialog reorders widgets with the same up/down buttons used elsewhere** (the older drag-the-row interaction was removed) for one consistent, keyboard-friendly model. ### Fixed - **On the smallest Budget widget size, the income and expenses line no longer truncates** both label and amount — it stacks vertically instead. ## [0.81.1] - 2026-07-01 ### Changed - **Kitchen modules (Meals, Recipes, Shopping) now share one consistent visual grammar.** A single module-accent strip lives on the shared tab bar and changes color with the active tab; recipe cards are opaque like the rest of the app instead of translucent glass; ingredient, meal and shopping quantities use aligned tabular figures; and the delete-undo window is a consistent 5 seconds across all three tabs. - **The Meals "add" button is now available on mobile**, matching Recipes and Shopping. - **The Recipe list now tiles across the available width on desktop** instead of a single column of full-width cards, and the Shopping list is centered in a readable column on wide screens. - **Recipe card actions** (edit, duplicate, delete) are now consistent, de-emphasized icon buttons that reveal on hover/focus, with delete no longer shown as a permanently visible red button. - **The active shopping list tab** now uses the Shopping module accent color. ### Fixed - **Recipe titles no longer overflow their card**, and the "open recipe link" no longer stretches the full card width with its label centered. - **The Recipes tab no longer shows a redundant page title** that the shared tab bar already provides. ## [0.81.0] - 2026-07-01 ### Added - **Undo for marking a loan installment paid** (Budget → Loans). The one money action that *creates* a commitment now has the same 5-second undo as deletions — a stray tap can be taken back without hunting down the payment. ### Changed - **Budget on mobile** now scrolls as a single view, so the floating add button no longer covers the last category or transaction. The module tab strip scrolls horizontally with a fade hint at the edge instead of clipping the last tab, and the active tab scrolls into view. - **Budget category labels** no longer truncate on tablet and desktop widths. - **Budget summary, loan, and loan-transaction surfaces** are now opaque for better legibility; the glass treatment is reserved for overlays. - **Budget statistics period** now shows localized dates instead of raw ISO dates. ### Fixed - **Budget statistics** now show a clear error state with a retry button when data can't be loaded, instead of a misleading "no data yet" message that looked like an empty history. - **Budget accessibility:** category amounts carry +/− signs (not color alone), the expense-breakdown donut keeps distinct colors for more categories, loan progress is announced as a progress bar, recurring markers are labeled for screen readers, and the module tabs support full keyboard navigation (arrow keys, Home/End, roving focus). ## [0.80.1] - 2026-06-30 ### Fixed - **Calendar event reminders now fire on time.** Event reminders were saved in local time while the notification scheduler compares against UTC, so they fired late by the local UTC offset and appeared not to arrive at all. Reminder times are now stored in UTC, consistent with task reminders, fixing Web Push, Gotify and ntfy delivery for calendar events. Existing event reminders fire correctly once the event is saved again. ## [0.80.0] - 2026-06-30 ### Changed - **Dashboard "Today at a glance" category labels** (Task, Event, Shopping, Dinner) now carry their module's accent color instead of neutral gray, reinforcing module identity at a glance. Contrast stays above WCAG AA in both light and dark themes. - **New installations now default to day-month-year date format** (e.g. `30.06.2026`) instead of US month-day-year, matching the existing 24-hour time and EUR currency defaults. Existing accounts keep their chosen format, and US `MM/DD/YYYY` remains selectable under Settings → Appearance. ### Fixed - **Duplicate required-field asterisk** removed: the title field in the task, calendar and budget dialogs no longer renders a doubled marker; a single styled asterisk is shown across all 20 languages. - **Dashboard meal widget** empty states no longer truncate mid-word — the dinner tile shows a concise "Nothing planned", and empty meal slots use a clearer muted placeholder. ## [0.79.0] - 2026-06-30 ### Changed - **Oikos → Yuvomi migration (automatic, no user action required):** the SQLite database file (`oikos.db` → `yuvomi.db`), the session cookie, browser storage keys, service-worker caches, the API-token prefix, and internal web-component/global identifiers are renamed to Yuvomi. On the first start after updating, an existing database is migrated in place, you stay signed in (the session cookie is migrated seamlessly), and stored preferences carry over. Existing Docker / Podman / Unraid / TrueNAS installations keep receiving updates without editing any configuration — the legacy `ghcr.io/ulsklyc/oikos` image mirror is retained permanently, and a `window.oikos` alias keeps pre-rename third-party modules working. - **Default database path** for new installations is now `/data/yuvomi.db` across all deploy targets (Docker Compose, Podman, Portainer, Unraid, TrueNAS, Quadlet). Existing `/data/oikos.db` installs are migrated automatically on boot; custom `DB_PATH` values are left untouched. - **Database backups** are now written with a `yuvomi-backup-` filename prefix; previously created `oikos-backup-` files remain restorable. - New API tokens use the `yuvomi_` prefix; existing `oikos_` tokens remain valid. ## [0.78.13] - 2026-06-30 ### Changed - **Dark mode accents restored to vivid:** reverted the one-step desaturation of dark-mode module accent colors introduced in 0.78.12 — the dark palette is lively again. The 0.78.12 dark-mode contrast fixes, the blue/teal hue separation, and the rosé Birthdays color are all retained. ## [0.78.12] - 2026-06-30 ### Changed - **Module accent colors rationalized:** the four near-identical blues are now visually distinct — Documents moves to a steel-blue and Split-expenses to an azure-cyan, while Recipes and Budget (previously the same teal hue) are separated. Birthdays moves to a rosé so it no longer clashes with the red used for delete/danger actions, and the Info color is decoupled from the byte-identical Contacts accent. - **Calmer dark mode:** module accent colors are desaturated one step in dark mode for a quieter palette without losing contrast. - **Glass tint:** module-accent tint on glass surfaces raised from 4% to 6% so each module's identity registers. ### Fixed - **Dark mode contrast:** primary button labels, info text, and the Documents and Split-expenses module accents now meet WCAG AA in dark mode (all were previously below the required contrast ratio). - **Design-token documentation:** corrected several inaccurate contrast ratios noted in the design tokens. ## [0.78.11] - 2026-06-30 ### Removed - **Dashboard stylesheet cleanup:** removed ~510 lines of dead and self-overriding CSS from `dashboard.css` — four unreferenced component generations (`.dashboard-metric`, `.dashboard-stat`, `.dashboard-kpi`, the old `.widget-greeting`/`.greeting-chip` block), an unused `.dashboard-chip`, a now-orphaned keyframe, and the redundant "Modern Skin" layer that a later block fully reverted. No visual change; rendered output is identical. ## [0.78.10] - 2026-06-30 ### Fixed - **Subscription cards:** removed the 4px colored left-border stripe; the brand color now lives solely on the brand icon tile, in line with the design system's full-border convention. - **Touch targets:** subscription card action buttons now meet the 40px minimum target size (were 36px), and the meal planner's "add another meal" button is raised to a full touch target on touch devices. - **Meal planner on touch:** the "add another meal" button, previously revealed only on hover, is now permanently visible on touch devices (`hover: none`), where it was otherwise unreachable. ## [0.78.9] - 2026-06-30 ### Fixed - **Offline cache isolation on logout failure:** the read-only offline API cache is now cleared even when the logout request itself fails (offline or unreachable server). Previously the cache clear was skipped if the logout POST threw, so a subsequent user on the same device could still fall back to the previous user's cached data. ## [0.78.8] - 2026-06-30 ### Added - **Read-only offline support:** the service worker now network-first-caches a whitelist of read-only `GET /api/v1/*` data paths (calendar, tasks, shopping, contacts, dashboard) in a release-keyed `oikos-api-` cache, so the last-seen data stays viewable when offline. The calendar shows a subtle "Offline – as of: {time}" banner (from the cached `x-cached-at` timestamp) when served from cache. (Discussion #388) ### Changed - **Service worker API handling:** mutations, `/auth/*`, and non-whitelisted GET requests are passed straight to the network and never cached; state-changing requests that fail offline now surface a clear "changes aren't possible while offline" message instead of a raw network error. ### Security - **Offline cache isolation:** the offline API cache is wiped on logout and session expiry so a second user on the same device cannot see the previous user's cached data, and stale `oikos-api-*` caches from prior versions are purged on every service-worker update. ## [0.78.7] - 2026-06-30 ### Changed - **Tasks → recurring tasks:** completing an overdue recurring task now schedules its next instance at the next occurrence on or after today, instead of advancing a single interval from the old (possibly still-overdue) due date. A skipped routine no longer reappears already overdue, and only one open instance ever exists. (Discussion #405) ## [0.78.6] - 2026-06-30 ### Fixed - **CI test suite:** updated the installer-schema test to expect the renamed internal shell variables (`YUVOMI_TZ`, `YUVOMI_PORT`) in `install.sh`, fixing the red `test:installer-schema` check after the Oikos→Yuvomi branding rename. ## [0.78.5] - 2026-06-30 ### Changed - **CalDAV/CardDAV sync:** updated the optional `tsdav` dependency to 2.3.0, keeping calendar/contact sync current and dropping the legacy `base-64` transitive package. - **Developer QA tooling:** updated Puppeteer to 25.2.1 for frontend audit and screenshot workflows. ### Fixed - **Pull request automation:** the Claude Code Review workflow now skips cleanly when `CLAUDE_CODE_OAUTH_TOKEN` is unavailable, so Dependabot PRs are not marked failed because review credentials are absent. ## [0.78.4] - 2026-06-30 ### Fixed - **Dashboard → Calendar deep links:** recurring events opened from the upcoming-events widget or Today Cockpit now jump to the displayed occurrence instead of the original series start date, and the popup/edit flow receives the expanded occurrence date. (PR #415) ## [0.78.3] - 2026-06-29 ### Fixed - **Meals → Mobile week view:** the meal planner now shows the full week (Mon–Sun) on phones instead of a fixed three-day window, so days 4–7 are reachable again. The week is stacked vertically, scrollable, and auto-scrolls to today on open. (Closes #416) ## [0.78.2] - 2026-06-29 ### Changed - **Third-party module documentation:** clarified that module API calls should use `/api.js` for built-in Yuvomi endpoints and that reverse-proxied dynamic backend services should live under a same-origin `/api/...` path to avoid stale service-worker cache responses. (Discussion #386) ### Fixed - **Dashboard → Today Meals widget:** hidden meal types from Settings → Modules → Kitchen are no longer rendered as empty slots in the widget. (Discussion #407) ## [0.78.1] - 2026-06-29 ### Added - **Meals → Weekly recurrence:** new meals can be marked as weekly repeats from the advanced meal dialog; Yuvomi materializes future occurrences on the same weekday, shows a repeat badge on recurring meals, and remembers skipped dates when a single occurrence is deleted. (Closes #412) ## [0.78.0] - 2026-06-29 ### Added - **Budget → Statistics tab:** new dedicated view with weekly/monthly/yearly range buttons, a period stepper, summary cards for income/expense/balance plus comparison against the previous period, an SVG trend chart of income vs. expenses, category bars, an expense-share donut, and a CSV-export button for the active range. Translated for all 20 locales. - **`GET /api/v1/budget/stats`:** new endpoint backing the Statistics tab — `?range=week|month|year&anchor=YYYY-MM-DD` returns totals, prior-period comparison, per-period series, and per-category breakdown. ### Changed - **`GET /api/v1/budget/export`:** also accepts `?from=YYYY-MM-DD&to=YYYY-MM-DD` to export an arbitrary date range; the legacy `?month=YYYY-MM` form keeps working. ## [0.77.9] - 2026-06-28 ### Changed - **Dashboard → Today meals:** the meals widget now visually matches the budget overview widget style — a 2×2 card grid with borders, rounded corners, muted backgrounds, and color-accented hover states. ## [0.77.8] - 2026-06-28 ### Changed - **Dashboard → Calendar deep links:** clicking an upcoming-events row or the Today Cockpit calendar card now navigates directly to the event detail popup (`/calendar?open=`) instead of just opening the calendar view. The calendar automatically jumps to the event's date and shows the detail popup on the matching chip; falls back to the edit modal when the chip is not in the rendered view. ## [0.77.7] - 2026-06-28 ### Changed - **Dashboard birthday widget:** avatars are now circular, matching the shape used for avatars throughout the app. ## [0.77.6] - 2026-06-26 ### Fixed - **Dashboard birthday widget:** the overview now shows upcoming birthdays from all household users instead of only birthdays created by the currently signed-in user. (Fixes #406) ## [0.77.5] - 2026-06-25 ### Fixed - **Weather widget: personal locations now show on the dashboard without a household weather provider:** a per-user Open-Meteo location now activates the weather proxy even when no admin household location is configured, so enabling the weather widget in the overview can render the user's own weather data. - **Translations: removed German placeholders from the personal weather and assignment UI:** all supported locales now translate the personal weather settings labels and the shared user multi-select "No one" copy instead of showing German fallback text. - **Dark mode: date-navigation arrows in Meals and Calendar are now visible on desktop:** the previous/next chevrons now use the app accent color instead of inheriting a dark/default icon color. ## [0.77.4] - 2026-06-25 ### Added - **Hungarian locale**: full Hungarian (`hu`) translation added, covering all UI strings across all modules (tasks, calendar, shopping, meals, budget, notes, contacts, birthdays, recipes, documents, housekeeping, settings, and more). Hungarian is now selectable in Settings → Language. The web installer wizard and CLI installer are localized as well. ## [0.77.3] - 2026-06-24 ### Fixed - **Split expenses: adding a family member as a group guest restricted their navigation to the Split page only:** when an existing user was added to an expense group with the `guest` role via the members endpoint, they were incorrectly written into the `split_expense_guest_users` table. This caused `access_scope` to be resolved as `split_guest` on their next login, hiding all navigation items except Budget/Split. The `split_expense_guest_users` table is now exclusively populated by the dedicated guest-account creation flow. A database migration removes existing incorrect entries for users who have no `guest_created` activity record. (Fixes #400) ## [0.77.2] - 2026-06-23 ### Fixed - **Shopping lists: can't check/uncheck items after switching lists:** switching to another list (or renaming one) re-bound the click handler on the persistent list container without removing the previous one, so each tap on an item's checkbox fired the toggle twice and cancelled itself out — only adding items still worked. The click delegation is now bound once per container. (Fixes #398) ## [0.77.1] - 2026-06-23 ### Fixed - **Missing `reminders.pushed_at` column after database rebuild:** migration 57 rebuilt the `reminders` table without carrying over the `pushed_at` column added in migration 54, causing `PushScheduler` to fail with `no such column: r.pushed_at` on every fresh install or update. A new migration restores the column. (Fixes #393) - **Schema-test export out of sync:** the node:sqlite-synchronized schema export used by tests had stopped at migration 61, so schema tests applying the exported migrations never picked up the restored `reminders.pushed_at` column. ## [0.77.0] - 2026-06-23 ### Fixed - **Calendar export feed: events with an explicit UTC offset:** events synced from sources that store an explicit timezone offset (e.g. Google Calendar, like `+02:00`) were exported with an invalid timestamp (`...+02:00Z`), producing `NaN` date/time values in the ICS feed instead of being converted to UTC. The export now correctly distinguishes offset-qualified timestamps from naive local ones. ## [0.76.0] - 2026-06-22 ### Added - **Read-only calendar export feed:** Settings → Calendar now lets any user expose their visible calendar events (own events, assigned events, and shared/own ICS subscriptions) as a `webcal://`/`https://` ICS feed for subscribing in Apple Calendar, Google Calendar, Thunderbird, and similar apps. Enabling the feed generates a secret token; "Regenerate link" rotates it (invalidating the old URL) and "Disable feed" clears it. The feed is served by a public, token-authenticated `GET /feed/calendar/:token.ics` route, rate-limited to 30 requests/minute per IP. (Discussion #387) ## [0.75.2] - 2026-06-20 ### Changed - **Settings overview polish:** the desktop Settings root now shows a descriptive overview instead of duplicating the local navigation, while status summaries, breadcrumbs, and mobile module rows use calmer system-aligned states and spacing. ## [0.75.1] - 2026-06-20 ### Added - **Gotify and ntfy notification channels:** admins can add household notification channels for self-hosted Gotify or ntfy servers alongside existing per-device Web Push. Reminder delivery now tracks each channel independently to avoid duplicate sends and preserve retry state. ## [0.75.0] - 2026-06-19 ### Added - **Per-user weather location:** any user — not just the admin — can now set their own weather location, units, and automatic-location-updates toggle under Settings → Personal → My Weather, overriding the household default just for their own dashboard widget. A status indicator shows whether a personal location or the household default is active, and a "Use household default" action clears the override. The dashboard's automatic location updates (introduced in v0.74.7) now write to this per-user override for every user instead of being admin-only. ## [0.74.8] - 2026-06-19 ### Fixed - **Missing translations for admin password reset:** the "New password" label, placeholder, and hint added to the "Edit member" dialog in v0.74.6 were only present in the German locale file, so every other language fell back to German text. All 18 non-German locales now have proper translations. (Fixes #372) ## [0.74.7] - 2026-06-19 ### Added - **Automatic weather location updates:** an opt-in "Standort automatisch alle 30 Minuten aktualisieren" checkbox in Settings → Modules → Dashboard re-requests the browser's geolocation every 30 minutes while the dashboard is open, silently updating the saved coordinates (admin-only). Enabling it immediately triggers the existing one-time location request. A stale city label is cleared on each automatic update so the widget falls back to showing coordinates instead of an outdated city name after the location changes. ## [0.74.6] - 2026-06-19 ### Added - **Admin password reset for family members:** the "Edit member" dialog now has an optional "Reset password" field (min. 8 characters, leave blank to keep the current password), so an admin can set a new password for a family member who forgot theirs — no SMTP/`BASE_URL` setup required, unlike the self-service "Forgot password" flow. Changing a member's password invalidates their other active sessions. (Fixes #372) ## [0.74.5] - 2026-06-19 ### Added - **Calendar click-to-create time pre-fill:** clicking an empty slot in the day or week view now pre-fills the new event's start time from the clicked position (rounded to the nearest 30 minutes), with the end time set to start + 1 hour. Previously the start time was always hardcoded to 09:00. ## [0.74.4] - 2026-06-18 ### Fixed - **Weather widget inset:** restored the card padding around current conditions and the forecast row, which was lost when the widget's wrapper was introduced in v0.74.3 and left its content flush against the card edges in contexts without the dashboard-specific override. ## [0.74.3] - 2026-06-18 ### Added - **Brazilian public holidays:** a local fallback (9 national holidays plus computed Good Friday) now populates the calendar when OpenHolidays returns no rows for `BR`, using Portuguese labels. - **Custom modules navigation group:** enabled third-party modules now get their own localized "Custom modules" sidebar section instead of being grouped under Home. ### Changed - **Weather widget sizing:** the dashboard weather widget now uses container queries instead of viewport media queries, so its layout density actually reflects its configured grid size instead of always forcing full width on larger screens. ### Fixed - **Help label fallback:** the navigation and help-page "Help" label no longer falls back to the German string "Hilfe" in non-German locales; all locales now show the correctly translated label. ## [0.74.2] - 2026-06-18 ### Fixed - **Calendar floating action button:** the keyboard focus ring now matches the active module accent color instead of always showing the global violet, and the button gets the documented top/bottom specular highlight for visual depth. ## [0.74.1] - 2026-06-18 ### Security - **Closed a DNS-rebinding gap in subscription logo discovery:** the validated public address is now pinned for the actual HTTPS connection instead of letting a second, independent DNS lookup decide where the request goes. - **Updated nodemailer** to fix several SMTP command-injection and CRLF-injection vulnerabilities (GHSA-c7w3-x93f-qmm8, GHSA-vvjj-xcjg-gr5g, GHSA-268h-hp4c-crq3, GHSA-wqvq-jvpq-h66f, GHSA-r7g4-qg5f-qqm2). ### Fixed - **Subscription logo HTML parsing** no longer double-unescapes encoded entities (e.g. `&lt;` no longer collapses to `<`). ## [0.74.0] - 2026-06-18 ### Changed - **Calmer create/edit modals across the app:** form dialogs now keep their module visible as a soft, tinted blur behind the panel instead of a full-screen takeover, and on mobile they open as a bottom sheet anchored to the lower edge. - **Progressive disclosure in heavy forms:** the most-used fields stay visible while secondary options collapse under a "More settings" section that auto-expands when editing an entry that already uses them. Applied to calendar events, tasks, budget entries, subscriptions, contacts, birthdays, meals, recipes, notes, and documents. ## [0.73.0] - 2026-06-18 ### Added - **Subscriptions tracker under Budget:** a new tab between Budget and Loans tracks daily, weekly, monthly, and yearly services with renewal dates, pause/disable state, custom categories and payment methods, search/filter/sort controls, uploaded or securely discovered logos, brand colors, and responsive mobile cards. - **Subscription budgeting and analytics:** configurable monthly budget, remaining/over-budget status, yearly projection, category and payment-method breakdowns, native-currency amounts, and optional Fixer-backed conversion into a household base currency with a 12-hour server cache. - **Subscription reminders:** per-subscription reminder timing feeds the existing in-app reminder center. - **Budget-linked subscription expenses:** every active subscription maintains its next payment as a Budget expense under a localized `Subscription` category. Subscription categories are mirrored as Budget subcategories, disabling removes the pending expense, and renewal preserves the paid entry while creating the next one. - **Redesigned subscription editor:** grouped identity, billing, renewal, organization, and service sections replace the flat form. The logo sits beside the name, currency/category/payment method use searchable in-modal lists, and logo discovery shows an immediate preview. - **Compact subscription dashboard:** the Subscriptions tab now uses the Budget accent tab color, Split-style page gradient, denser subscription rows, compact summary cards, a renewal forecast area chart, category pie chart, and payment-method breakdown. - **Selectable subscription logo search:** logo discovery now opens a picker with site-owned candidates (declared icons, favicon, Open Graph image) so users can choose the exact logo before saving. ### Security - **Protected external subscription integrations:** all subscription APIs require the existing authenticated session and CSRF middleware; logo discovery validates every public HTTPS redirect, blocks private/link-local addresses, reads only bounded page/search metadata, and constrains remote image size/type. ### Fixed - **Subscription settings and logo discovery:** the base currency now uses the searchable currency picker, an unset subscription budget is shown as unlimited instead of over budget, and logo search tries page icons plus the standard favicon without failing on large page bodies. - **Subscription service-name logo search:** plain service names now generate likely public domain candidates and inspect those sites directly under the existing SSRF protections, and logo search failures surface in the UI while detailed diagnostics are written to server logs. - **Subscription modal polish:** the next payment field now uses the native date picker, the billing cycle control no longer relies on the unstable native select in the modal, and newer subscription labels are localized across all supported languages. ## [0.72.0] - 2026-06-17 ### Added - **Budget category management (#357):** a "Manage categories" button in the Budget tab header opens a modal to rename, reorder, and delete budget categories and their subcategories, built on a reusable `oikos-category-manager` web component. Deletion is blocked while a category or subcategory is still referenced by entries, or when it is the last category of its type / last subcategory of its category. ## [0.71.51] - 2026-06-17 ### Added - **SMTP email & self-service password reset**: administrators can configure an SMTP server under Settings → Administration → Email (or via the `EMAIL_SMTP_*` / `EMAIL_FROM_*` environment variables), with a "Test connection" button to validate the setup. Once email is configured, the login page offers a "Forgot password?" link — users request a reset by username or email and receive a time-limited (1 hour) reset link. The absolute origin for reset links is taken from the new `BASE_URL` setting. ### Security - Password-reset links are built only from the configured `BASE_URL` and never from the request Host header (host-header / reset-poisoning protection). The forgot-password endpoint always returns a generic response to prevent account enumeration, reset endpoints are rate-limited, and tokens are single-use, hashed at rest, and expire after one hour. The configured SMTP password is never returned by the API. ## [0.71.50] - 2026-06-16 ### Added - **Web Push notifications for reminders**: opt-in push notifications (Settings → Personal → Notifications) deliver due reminders as system notifications even when the app is closed. A background scheduler sends due task, event and birthday reminders via the Web Push standard (VAPID / RFC 8291); VAPID keys are generated automatically on first use, or can be pinned across redeployments via `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY` and `VAPID_SUBJECT`. Requires HTTPS. On devices where push is enabled, the in-app reminder toast still appears while the duplicate in-page browser notification is suppressed. ## [0.71.49] - 2026-06-16 ### Added - **Unified Region / Format setting**: a single Region dropdown in Appearance settings presets currency, date format and time format together for 24 supported locales (e.g. de-DE, en-US, pt-BR). Selecting "Custom" reveals the individual currency, date and time controls. The Region control is admin-only, matching the previous currency permission. ### Changed - **Currency moved out of Budget settings**: the currency selector now lives in the unified Region / Format control in Appearance settings; the Budget settings page links there instead. ## [0.71.47] - 2026-06-15 ### Changed - **Weather widget appears first on the dashboard**: the default dashboard layout now places the weather card above the tasks and calendar widgets, so it is visible at the top without scrolling. This applies to new installs and anyone who has not customised their widget order; existing custom layouts are preserved. ## [0.71.46] - 2026-06-15 ### Fixed - **Editing an hourly housekeeping visit no longer fails with "daily_rate is required"**: saving changes to a visit billed by the hour (e.g. adjusting the hours worked) returned a 400 error because the update endpoint always demanded a daily rate, even though hourly visits submit minutes worked instead. The daily rate is now only required for daily-rate visits; hourly visits recompute the amount from the minutes worked. ## [0.71.45] - 2026-06-15 ### Fixed - **Settings side navigation updates its language on locale switch**: changing the application language while on a Settings page left the side navigation menu and the page header in the previous language until a hard reload. The Settings shell now tracks the locale it last rendered with and performs a full re-render when it changes, so the labels update immediately like the rest of the app. ## [0.71.44] - 2026-06-14 ### Changed - **Holiday data syncs at most once every 30 days**: the automatic background holiday sync no longer calls the OpenHolidays API on every sync cycle (every 15 minutes by default) — it now skips when the cache was refreshed within the last 30 days, cutting needless external requests for data that changes at most yearly. The manual "Sync now" button in Settings still forces an immediate refresh. ### Fixed - **"Heute wichtig" calendar card shows only today's events**: the dashboard Today Cockpit's calendar card listed the next upcoming event even when it was days away; it now counts and shows only events that fall on the current day. - **DMS account action buttons aligned inside the card**: the Test/Remove buttons for a connected document-management account are now rendered inside the account's status card instead of spilling outside its border. ## [0.71.43] - 2026-06-14 ### Added - **Visible help entry**: a "Hilfe" item now sits in the desktop sidebar and in the mobile "More" sheet, opening a help overlay. On desktop it lists the keyboard shortcuts; on touch devices (where shortcuts don't apply) it shows a short plain-language guide — how to navigate, create with the + button, search, and find settings. The `?` keyboard shortcut still opens the same overlay. ## [0.71.42] - 2026-06-13 ### Changed - **Contact category icons** now use Lucide line icons (stethoscope, graduation cap, landmark, shield, wrench, …) instead of emoji, matching the line-icon style used across the rest of the app. - **Calendar event colour shown as a dot**: the agenda list and the dashboard calendar widget now mark an event's calendar colour with a small dot instead of a coloured bar on the card's edge, using the same vocabulary as the task list's status dots. - **Tasks filter row uses the module accent**: the active filter chip, the clear badge, and the filter toggle now use the Tasks green instead of the global violet, so the filter row matches the rest of the module. ### Fixed - **Single way to add a recipe**: Recipes no longer shows a toolbar "Add recipe" button next to the floating action button; the floating action button is now the only create action, consistent with every other module. - **Calendar names with "&" display correctly**: external calendar names that arrived HTML-entity-encoded (e.g. an imported Google calendar shown as "Termine & Verabredungen") are now stored and displayed as plain text; existing names are repaired automatically. ## [0.71.41] - 2026-06-13 ### Changed - **Consistent module headers across the app**: every module now shows a same-sized page title and a shared, slot-based toolbar — the title sits left, search or date navigation in the centre, and view switchers and actions grouped on the right — so the header no longer changes size or layout when moving between Tasks, Documents, Notes, Housekeeping, Contacts, Budget, Kitchen, Calendar, and Birthdays. On phones the centre slot (search/date navigation) drops to its own row as a cohesive group. - **Kitchen shows a "Küche" title**: the Meals/Recipes/Shopping tab bar now carries the module title beside the tabs. - **Calendar view switcher matches Budget**: the active Month/Week/Day/Agenda tab now uses the module-accent fill instead of a neutral pill, giving segmented switchers one consistent active style. ### Fixed - **Single way to add in Documents and Birthdays**: these modules previously showed both a toolbar button and a floating action button to create an item; the floating action button — in the module's own colour — is now the only one. - **No more duplicated search label**: the search field in Documents, Contacts, and Birthdays no longer repeats its placeholder text as a visible label above the box. - **No stray focus outline on settings titles**: opening a settings page no longer draws an accent box around the page title. ## [0.71.40] - 2026-06-13 ### Fixed - **Week view day numbers highlight on hover again**: hovering a non-today day header in the calendar's week view now shows the intended circular highlight; it previously referenced an undefined colour token and had no effect. ### Changed - **Dashboard "Today at a glance" is easier to scan on phones**: the important-today cards now use a compact 2×2 glance grid instead of a full-height stack, so the actionable lists below appear without scrolling; very narrow screens fall back to a single column. - **Dashboard glance cards read more calmly**: the task and event cards show an open-count badge and now use neutral titles with a single coloured module icon, reducing the colour load at the top of the screen. ## [0.71.38] - 2026-06-13 ### Fixed - **All-day events now appear in the dashboard's upcoming events widget**: events stored with a date-only timestamp (no time component) were excluded by an off-by-one string comparison; they are now handled correctly. - **Birthdays set to "no notification" no longer appear as calendar events**: selecting "keine Benachrichtigung" now removes the associated calendar event so the birthday is no longer shown in upcoming events or the calendar view. ## [0.71.37] - 2026-06-13 ### Changed - **Mobile controls are easier to operate**: task filters, Calendar's Today action, loan filters, and Settings breadcrumbs now use consistent touch-safe targets. - **Progress indicators animate without layout work**: Dashboard shopping progress and task subtask progress now use transform-based animation. ### Fixed - **Shared dialogs and Housekeeping expose clearer semantics**: prompt and selection fields have accessible labels, and Housekeeping starts with a proper page heading. - **User-selected and semantic colors remain readable**: avatars choose a contrasting foreground automatically, while priority and meal labels meet WCAG AA contrast in light and dark themes. ## [0.71.36] - 2026-06-13 ### Changed - **Dense mobile modules now reveal complexity progressively**: Contacts keep one primary row action with secondary actions under More, Documents collapse view and filter controls behind a bounded overflow panel, and Navigation settings use lighter sections with a sequential heading hierarchy. - **Mobile controls now use consistent touch-safe sizing and quieter motion**: meal actions remain visible with 48 px targets, audited profile, birthday, navigation, contact, housekeeping, and budget controls meet the same target standard, and budget bars animate with transforms instead of layout-driving widths. ### Fixed - **Forms, housekeeping copy, and holiday chips are more accessible**: search fields retain visible labels, German housekeeping strings no longer fall back to English, worker identity spacing is restored, and custom holiday colors choose readable foreground text. ## [0.71.35] - 2026-06-13 ### Fixed - **Dashboard interactions now feel proportionate and respond on the first mobile swipe**: the "Today important" values no longer overpower their heading, the initial route skips the page-slide transform, and the closed quick-action layer no longer captures gestures in the lower half of the screen. - **Calendar gains clearer desktop spacing and denser date navigation**: the page now keeps a consistent gutter beside the sidebar, while weekday and date sit side by side in a shorter header row. - **Settings open faster and mobile navigation accents stay distinct**: Settings reuse the authenticated router user instead of repeating the session request, and Dashboard and Calendar retain separate colors in light and dark themes. ## [0.71.34] - 2026-06-13 ### Fixed - **PWA updates and final interface details now remain current, readable, and consistent**: release-bound service-worker caches deliver every published UI revision, the early locale bootstrap remains available offline, colored Notes choose WCAG-safe text automatically, Dashboard quick actions use native controls with one clear page heading, mobile customization keeps a 48 px touch target, and rounded Dashboard and Housekeeping cards use quieter full borders instead of heavy accent caps. - **Docker publishing no longer reports a failed release after images were pushed successfully**: transient GitHub Actions cache-export errors are treated as failures of an optional optimization, while image builds and registry pushes remain strict. ## [0.71.33] - 2026-06-12 ### Fixed - **RTL, extreme-content, and route-error resilience are hardened across the responsive UI**: Arabic now applies RTL before first paint and re-renders the active page when languages change; mixed-script and unbroken Notes and Birthdays content stays within its layout; adapted search and overflow controls align logically; and failed page loads show a localized, focused recovery state instead of raw network errors or false empty data. ## [0.71.32] - 2026-06-12 ### Changed - **Responsive module layouts now preserve readability from narrow phones through tablets**: Notes use width-aware grid columns without horizontal overflow, dense Tasks and Documents controls collapse or wrap before labels are squeezed, Kitchen tabs remain visible, Settings overview links use tablet space efficiently, dashboard note cards constrain long content, and Birthdays presents one clear mobile creation action. ## [0.71.31] - 2026-06-12 ### Changed - **App-wide typography now follows one responsive semantic hierarchy**: mobile and desktop use fixed hero, page, section, card, body, secondary, caption, and micro roles instead of drifting module-specific sizes. Oversized mobile headings were reduced, readable supporting text now starts at 14px, prose and inputs stay at 16px, document and split-expense headings are consistent, and Settings leaf pages show one clear primary title. ## [0.71.30] - 2026-06-12 ### Changed - **Mobile bottom navigation now uses a quieter, more precise active state**: the inset module-tinted indicator, flatter inactive icon wells, stable labels, focused keyboard ring, and icon-only press feedback improve clarity across light, dark, reduced-motion, reduced-transparency, high-contrast, and forced-color modes. ## [0.71.29] - 2026-06-12 ### Fixed - **WebDAV document storage now works with local/private-network targets**: setting `DOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK=true` lifts the SSRF block for Nextcloud or other WebDAV servers that resolve to RFC 1918 / loopback addresses (e.g. same Docker Compose stack, LAN domain via Caddy). The guard remains active by default; the opt-in is explicit and documented. ## [0.71.28] - 2026-06-12 ### Fixed - **Relative `DB_PATH` no longer crashes with a cryptic error**: `init()` now creates the database directory before opening the connection (consistent with the existing restore path) and logs a clear warning when `DB_PATH` is relative, explaining that data will not survive container restarts and pointing to the correct absolute-path form (`/data/oikos.db`). ## [0.71.27] - 2026-06-12 ### Fixed - **Website version badge synchronized**: the GitHub Pages landing page now shows the current release in both the proof bar and footer instead of the stale `v0.71.21` label. ## [0.71.26] - 2026-06-12 ### Changed - **Responsive navigation personalization**: the mobile bottom bar now keeps exactly five stable destinations visible — Overview, three user-selected favorites, and More — and remains present while content scrolls. Inactive buttons use neutral surfaces while the current module alone carries its accent through a faster 200 ms sliding indicator. Settings → Modules → Navigation now separates mobile favorites from web navigation; desktop entries can only be reordered within the Overview, Plan, and Home groups, with Dashboard and Settings pinned. ## [0.71.25] - 2026-06-12 ### Fixed - **Settings page no longer shifts horizontally when the scrollbar appears or disappears**: `.app-content` now declares `scrollbar-gutter: stable`, which pre-reserves the scrollbar lane at all times. Previously, toggling between long and short pages caused the entire content area to jump by the scrollbar width. ## [0.71.24] - 2026-06-12 ### Fixed - **Dashboard scroll on Android no longer requires a tap before the first swipe**: interactive cards (`.today-cockpit-card`, `.dashboard-metric`) were missing `touch-action: pan-y`, causing Chrome to enter tap/scroll disambiguation mode on the first touch. A preliminary tap was needed to activate the scroll context. All dashboard interactive items now declare `touch-action: pan-y` consistently, so the first swipe scrolls immediately. ## [0.71.23] - 2026-06-12 ### Fixed - **Task reminders no longer drift by the timezone offset on every save**: a task reminder was stored as UTC but read back as local time, so reopening a task in a non-UTC timezone showed the wrong offset (e.g. "1 hour before" became "Custom – 360 minutes" at UTC+5), and each save without changes added the offset again. Reminder times are now read back as UTC consistently, so the offset round-trips correctly and stays stable across repeated saves. ## [0.71.22] - 2026-06-12 ### Changed - **Collapsible settings sidebar on desktop**: the settings navigation (≥1024px) used to list every domain and all its pages at once, which ran very long for admins (5 sections, 18 links). The five domain groups (Personal, Modules, Sync, Documents, Administration) are now a single-open accordion: the domain you are currently in is expanded and the others collapse to just their header, with a smooth height animation and a rotating chevron. Switching pages automatically opens the matching domain and closes the rest. Collapsed sections are removed from the keyboard tab order, the open/close motion respects reduced-motion preferences, and the accordion only activates when more than one domain is visible (single-domain members keep the flat list). The mobile drill-down navigation is unchanged. ## [0.71.21] - 2026-06-12 ### Changed - **Slimmer dashboard header on mobile**: the home dashboard header used to stack three rows on phones (date, greeting, then the customize button on its own line). The customize button now sits on the greeting row, right-aligned and vertically centered, so the header takes less vertical space and "Today at a glance" appears sooner. The desktop layout and the edit-mode toolbar (which still wraps below on narrow screens) are unchanged. ### Removed - **Dead dashboard styles and a deprecated token**: removed unused CSS for the previous dashboard layout system (hero, layout, workspace, tile, side-stack, and the `dashboard-widget-grid` class) that was left behind when the current widget grid replaced it, and dropped the deprecated `--text-md` font-size alias. Internal cleanup only, no visible change. ## [0.71.20] - 2026-06-12 ### Changed - **Calmer dashboard above the fold**: the home dashboard no longer stacks three separate representations of the same four areas (Tasks, Calendar, Shopping, Meals) before any new information appears. The redundant quick-action row in the greeting header has been removed — the bottom-right action button (and the sidebar on desktop) already cover creating and navigating — so the personal greeting and the "Today at a glance" summary now lead the screen. On mobile this also removes a row of unlabeled icon-only buttons. The duplicate date that the summary repeated directly under the greeting is gone, leaving a single date. No data, widgets, or customization were changed. ## [0.71.19] - 2026-06-12 ### Fixed - **No false translation prompt on non-German devices** (#353): the app shipped a hardcoded ``, so Chromium-based browsers (e.g. Brave) repeatedly offered to translate the already-localized interface from German on non-German systems. The document language is now set to the resolved user locale before the page renders, so the declared language matches the displayed content. ## [0.71.18] - 2026-06-12 ### Changed - **Modal size reference completed**: the `openModal({ size })` documentation now lists all four sizes (`sm`/`md`/`lg`/`xl`) with their widths, matching the CSS and the design system instead of omitting the `xl` size that the Documents module already uses. ### Removed - **Dead loading translation keys**: two unused `loadingIndicator` strings (Recipes and Budget) were removed across all 19 locales; the shared skeleton loading state replaced them in v0.71.14–0.71.17. ## [0.71.17] - 2026-06-12 ### Fixed - **Loading skeletons now appear on first navigation**: opening a page used to show a blank content area until its data finished loading, because the router only revealed a page once its `render()` (including the data fetch) had fully resolved, so any skeleton placed before that fetch never showed. The page shell and its loading skeleton now appear immediately while data loads, so every module gives feedback on slow connections instead of looking stuck. - **Skeleton contrast in dark mode**: skeleton placeholder lines were nearly invisible against the dark card surface. Their colour is now mixed from the surface and text colours, so they have clear, consistent contrast in both light and dark themes. ### Changed - **Skeleton loading for the remaining list modules**: Contacts, Notes, Birthdays, Documents, Recipes, and Shared expenses now show the shared skeleton loading language while their lists load, completing the rollout so all modules use one consistent loading state. ## [0.71.16] - 2026-06-12 ### Changed - **Container-query responsive layout**: component-internal grids now reflow by their own available width instead of the viewport. The notes board, meal-day slots, budget summary cards, modal two-column forms, and the dashboard "today at a glance" strip and overview header all use CSS `@container` queries. Sidebar-aware result: a narrow modal on a wide desktop, or a panel squeezed by the sidebar, collapses based on its real width rather than the window size. - **Canonical breakpoints**: roughly 33 ad-hoc viewport breakpoints (900/820/780/720/700/680/600/599/560/520/480/420/959/960/980/1100/1180/1200/1280px) were consolidated onto the four documented boundaries (640/768/1024/1440px), so layout transitions are consistent across modules. ### Fixed - **Side-stripe accents removed**: the colored left-border stripes on the dashboard "today at a glance" cards and on calendar holiday chips are gone; module/holiday identity is now carried by the full border, background tint, and icon for a cleaner, more consistent look. ### Removed - **Dead dashboard CSS**: eight unused responsive blocks for never-rendered layout-generation classes were removed. ## [0.71.15] - 2026-06-12 ### Changed - **Consistent loading feedback**: a shared skeleton loading language (`public/utils/skeleton.js` → `renderSkeletonList()`) replaces the per-module "loading…" text placeholders in Budget, Meals, and Housekeeping. The skeleton classes (`.skeleton-list`/`.skeleton-card`/`.skeleton-line`) now live globally in `layout.css` instead of only in `dashboard.css`. - **Z-index discipline**: the two remaining magic-number z-indexes (`9999` skip link, `1000` kanban drag ghost) are mapped to new semantic tokens (`--z-skip-link`, `--z-drag`) on the documented scale. ### Fixed - **Skeleton widths outside the dashboard**: the `.skeleton-line--short/medium/full` variants previously lived only in `dashboard.css` and silently had no effect on other pages (Tasks, Shopping), because CSS is loaded per module; they are now globally available. - **Skeleton and reduced motion**: the skeleton shimmer now respects `prefers-reduced-motion: reduce` (static surface instead of animation). ## [0.71.14] - 2026-06-12 ### Changed - **Typography consistency**: unified font sizes, weights, line-heights, and letter-spacing across every module and sub-module (dashboard, calendar, tasks, budget, kitchen, settings, and the rest) behind a shared typographic role layer. Page titles, section headings, eyebrow labels, and card titles now render consistently on mobile and desktop. Font sizes and letter-spacing are fully token-driven, and canonical breakpoint tokens document the mobile/tablet/desktop/wide boundaries. ### Fixed - **Label legibility**: meal-slot type labels and several uppercase section/eyebrow labels used the too-faint "disabled"/"tertiary" text colors; they now use the readable secondary text color, improving contrast and visual consistency. ## [0.71.13] - 2026-06-11 ### Changed - **Docs**: updated installation guide, SPEC, and Unraid CA template to document the `OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM` opt-in variable introduced in v0.71.11. ## [0.71.12] - 2026-06-11 ### Security - **OIDC account linking (revert v0.71.11)**: the relaxed `email_verified !== false` check introduced in v0.71.11 is replaced with a strict opt-in. The default is restored to `email_verified === true` required; the new `OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM=true` env var lets admins opt in explicitly for IdPs that omit the claim but only issue verified addresses. ## [0.71.11] - 2026-06-11 ### Added - **`OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM`** env var (opt-in): set to `true` to allow account linking when the IdP omits the `email_verified` claim entirely. The default remains strict (`email_verified: true` required) to prevent account-takeover via unverified addresses. Only enable this for IdPs fully under your control that never issue accounts with unverified email addresses (e.g. older Authentik deployments without an explicit `email_verified` property mapping). ## [0.71.10] - 2026-06-11 ### Fixed - **CI test fix**: updated `test-frontend-audit` assertion for the DMS settings page to check for both `paperless` and `papra` provider option values, replacing the old static `provider: 'paperless'` literal that no longer exists after the multi-provider select was introduced in v0.71.9. ## [0.71.9] - 2026-06-11 ### Added - **Papra DMS integration**: Papra is now a second supported document management system alongside Paperless-ngx. Admins can connect a Papra instance by selecting "Papra" from the provider selector in Settings → Documents → Document management, entering the server URL, organization ID, and API token. The adapter layer handles search, link, upload, and connection test; existing Paperless-ngx connections are unaffected. DB migration v52 adds the column and updates the CHECK / UNIQUE constraints on . ## [0.71.8] - 2026-06-11 ### Fixed - **Settings nav link**: tapping "Settings" in the mobile nav bar or the overflow sheet now opens the settings overview instead of jumping directly to the last-visited settings page. ## [0.71.7] - 2026-06-11 ### Added - **Recurring payment series management**: deleting or editing a recurring budget entry now asks whether to affect only the current occurrence or the entire series. "Delete entire series" removes the parent rule and all its instances; "Change all future occurrences" updates the parent rule and purges future instances so they regenerate with the new values on next visit. ## [0.71.6] - 2026-06-11 ### Changed - **Consistent Settings cards**: every card across the settings pages now shares one surface style. A few cards that still rendered with a translucent "glass" background have been brought in line so all cards match. ## [0.71.5] - 2026-06-11 ### Fixed - **SSO account matching**: signing in via OIDC no longer always creates a new account (e.g. `username-1`) when one with the same email already exists. An existing local account is now linked automatically when the provider reports a verified email (`email_verified: true`) and exactly one account holds that address. Unverified or ambiguous emails still get a separate account, preventing account takeover. ## [0.71.4] - 2026-06-11 ### Changed - **Faster Settings navigation**: switching between settings pages now swaps only the content area instead of re-rendering the whole screen. The side menu stays put and pages change instantly — without a reload, an extra authentication round-trip, or a slide animation. Browser back/forward between settings pages is just as fast. - **Consistent Settings headings**: section headings are now larger than the cards they group, fixing an inverted type hierarchy where group titles appeared smaller than the content beneath them. ## [0.71.3] - 2026-06-11 ### Changed - **WebDAV backup default path**: changed from `/oikos/backups/` to `/yuvomi/backups/` to reflect the app rename. Existing installations with a saved or explicitly configured path are not affected. ## [0.71.2] - 2026-06-11 ### Fixed - **Settings credentials inputs**: replaced incorrect `autocomplete="new-password"` with `current-password` on external-service password fields (WebDAV document storage, DMS token), and replaced `autocomplete="username"` with `off` on external-service username fields (WebDAV backup, CalDAV, CardDAV, document storage) to prevent browsers from auto-filling app login credentials into unrelated service forms. ## [0.71.1] - 2026-06-11 ### Fixed - **Calendar week and day view timeline**: hour labels on the left now respect the AM/PM time format preference. Previously the timeline always showed 24-hour labels even when AM/PM was selected in Settings. ### Security - **Storage test endpoint**: added SSRF pre-flight check to `/storage/test` so UI-initiated connectivity tests cannot reach private, loopback, or link-local addresses. ## [0.71.0] - 2026-06-11 ### Changed - **Settings reorganized into five clear areas**: Settings is now grouped into **Personal**, **Modules**, **Sync**, **Documents**, and **Administration**, each with its own focused pages instead of one long row of tabs. Members see only Personal; administrators see everything. On a wide screen a sticky side menu keeps every page one click away; on a phone you drill down from an overview into an area and into a page, with breadcrumbs and a working Back button. Each page loads on demand and remembers where you were. - **Synchronization is organized by what you sync** — separate **Calendar**, **Contacts**, and **Reminders** pages, each opening with a clear connection status. CalDAV and Webcal/ICS are front and center; Google and Apple/iCloud now live under a **"More providers"** section, with Apple marked as legacy and new iCloud users pointed at the standard CalDAV setup. - **Documents has its own area** with separate **Document storage** (local/WebDAV) and **Document management (Paperless/DMS)** pages; database-backup settings stay under Administration. - **Kitchen is one place in the navigation**: Meals, Recipes, and Shopping are grouped under a single **Kitchen** entry you can reorder as one item, while each still has its own page. The main navigation is grouped into **Overview**, **Plan**, and **Home**. - **Shopping categories are managed inside Shopping** (via a "Manage categories" action) instead of in Settings. Old Settings links and bookmarks are redirected to the right new place automatically. ### Fixed - **Opening Settings directly now works reliably**: loading, refreshing, or bookmarking the Settings URL no longer occasionally lands on the dashboard. ## [0.70.2] - 2026-06-10 ### Security - **WebDAV document storage**: UI-managed targets now reject private, loopback, link-local, internal-DNS, and DNS-rebinding destinations both before persistence and during socket lookup. Trusted private-network targets remain available through `DOCUMENT_STORAGE_WEBDAV_URL`. - **WebDAV path normalization**: replaced ambiguous trailing-slash regular expressions with linear path processing to prevent polynomial-time matching on attacker-controlled configuration. ## [0.70.1] - 2026-06-10 ### Removed - **Repository metadata**: removed the last published reference to an internal development tool. ## [0.70.0] - 2026-06-10 ### Added - **WebDAV document storage**: admins can select WebDAV as the global destination for new document files, including calendar attachments, with per-field environment overrides, connection tests, protected configuration changes, and clear local/WebDAV/DMS status throughout the interface. ### Changed - **Document binary handling**: previews, downloads, calendar attachments, deletion, and Paperless/DMS uploads now share one storage layer. Existing local files stay local, failed WebDAV uploads never fall back silently, failed database writes clean up staged remote files, and database backups explicitly exclude WebDAV binaries, which must be backed up separately. ## [0.69.0] - 2026-06-10 ### Added - **Documents — Paperless-ngx (DMS) integration**: admins can connect a Paperless-ngx document management system in Settings (server URL + API token, with a connection test). Multiple DMS accounts are supported. - **Link from DMS**: search a connected DMS and link existing documents into the Documents module as references — the binary stays in the DMS and is not duplicated. Previews and downloads of linked documents are proxied live from the DMS, while each document's family/restricted/private visibility is still enforced. - **Upload to DMS**: push a local document up into the connected DMS (asynchronous OCR ingestion); when several DMS accounts are configured, an account picker lets you choose the target. All DMS operations are admin-only, and the API token is never returned in responses. The integration uses a provider-pluggable adapter layer (Paperless-ngx is the first adapter) and requires no new environment variables — everything is configured in-app. ## [0.68.4] - 2026-06-09 ### Fixed - **Documents**: PDF previews no longer fail with "This page was blocked by Chrome" in Chromium-based browsers. The preview iframe dropped its `sandbox` attribute (Chromium refuses to start its internal PDF viewer inside sandboxed frames) and the `/documents/:id/preview` endpoint now sends a PDF-specific Content-Security-Policy (`default-src 'self'`) instead of the strict `default-src 'none'` that blocked the native viewer. PDFs are still served same-origin as `application/pdf` with `X-Content-Type-Options: nosniff`, so no scripts can execute; non-PDF previews keep the strict policy. ## [0.68.3] - 2026-06-09 ### Changed - **Dashboard**: assignee avatars in the calendar widget's event rows are now 28px, matching the tasks widget and the app-wide default. They were previously 26px — a slight outlier — so the two side-by-side dashboard widgets now present assignees at a consistent size with better visual presence. ## [0.68.2] - 2026-06-09 ### Fixed - **Desktop sidebar**: collapsing/expanding the navigation sidebar no longer makes the icons, logo, and toggle button jump horizontally. Elements now keep stable horizontal centers and the toggle button's padding transitions smoothly in sync with the width animation, instead of snapping via instant `justify-content` changes. ## [0.68.1] - 2026-06-09 ### Security - **Documents preview**: hardened the new `GET /api/v1/documents/:id/preview` endpoint with defense-in-depth against stored XSS. It now enforces its own server-side allowlist of previewable MIME types (PDF, PNG, JPEG, WebP, plain text, CSV) and returns `415` for anything else, instead of serving any stored `mime_type` inline. Responses additionally carry `X-Content-Type-Options: nosniff` and a restrictive `Content-Security-Policy` (`default-src 'none'`) so no inline content can execute scripts even if a file were ever misclassified. (Not exploitable in 0.68.0 — uploads already reject HTML/SVG — but this removes the implicit dependency on the upload allowlist.) ## [0.68.0] - 2026-06-09 ### Added - **Documents**: in-browser document viewer. Uploaded files can now be previewed directly in an `xl` modal without downloading — images (PNG/JPEG/WebP) render inline, PDFs open in a sandboxed same-origin iframe, and text/CSV files are fetched and shown in a monospaced block. Office files (Word/Excel) and other non-previewable types fall back to a download prompt. A new eye-icon action button appears on viewable files, and clicking a card or row opens the viewer. Backed by a new `GET /api/v1/documents/:id/preview` endpoint serving files with `Content-Disposition: inline`. ### Changed - **Documents**: grid cards redesigned — the category icon and date now share a header row, with action buttons centered below a divider. ### Security - The Content-Security-Policy `frame-src` directive was relaxed from `'none'` to `'self'` to allow same-origin PDF embedding in the document viewer. The PDF iframe is additionally `sandbox`ed (`allow-same-origin` only, no scripts) as defense-in-depth. ## [0.67.6] - 2026-06-09 ### Fixed - **Docker/Podman**: `BACKUP_DIR` in `docker-compose.yml` and `podman-compose.yml` is now hardcoded to `/backups` in the container's `environment:` section. Previously, setting `BACKUP_DIR=./backups` in `.env` to control the host-side volume mount source would also inject that host path into the container, where it does not exist — causing backups to fail silently. The container-side mount target is always `/backups` (fixed in `volumes:`), so the env var is now set unconditionally to that value. ## [0.67.5] - 2026-06-09 ### Security - Added `Content-Security-Policy` and `Referrer-Policy` meta tags to all landing-site pages (`index.html`, `install.html`, `impressum.html`, `datenschutz.html`). The CSP restricts resources to same-origin plus the inline styles/scripts the pages actually use; the referrer policy is `strict-origin-when-cross-origin`. (Clickjacking headers such as `X-Frame-Options`/`frame-ancestors` only take effect as real HTTP headers and cannot be enforced on plain GitHub Pages.) ## [0.67.4] - 2026-06-09 ### Added - Privacy guide for self-hosters (`docs/PRIVACY-FOR-SELFHOSTERS.md`): per-service third-country assessments for every external integration (Open-Meteo/OpenWeatherMap weather, CalDAV/CardDAV sync, OIDC single sign-on, WebDAV backup), data-processing-agreement notes, GDPR log-retention guidance, a household-exemption explainer, and a records-of-processing template. Linked from the README, the installation guide, and `.env.example`. ## [0.67.3] - 2026-06-09 ### Added - Imprint (`impressum.html`) and privacy policy (`datenschutz.html`) pages for the yuvomi.cloud landing site, linked from the footer of every public page. ### Changed - The landing page now embeds the GitHub star count at build time (`scripts/update-gh-stars.mjs`, refreshed by a weekly workflow) instead of fetching the GitHub API from the visitor's browser — so opening the page no longer transmits any visitor data to a third party. - Clarified the AES-256/SQLCipher database encryption as optional (enabled in the recommended Docker setup) across the README, landing page, and SECURITY.md, to match the actual default install. - Corrected the session/CSRF cookie description in SECURITY.md from `SameSite=Strict` to `SameSite=Lax` to match the implementation, with a note on the Safari ITP rationale and Double-Submit-Cookie CSRF protection. ## [0.67.2] - 2026-06-09 ### Changed - Redesigned the GitHub social preview and Open Graph image (`docs/social-preview.png`, `docs/og-image.png`) with a more modern, professional editorial layout: brand logo mark and wordmark, a kicker pill, a gradient headline, feature chips with real icons, and the dashboard shown inside a macOS-style window frame with an ambient glow. The internal generator (`scripts/generate-social-preview.mjs`) was rewritten to embed the Plus Jakarta Sans brand font for crisp, on-brand typography. Image paths are unchanged, so existing Open Graph references keep working. ## [0.67.1] - 2026-06-09 ### Changed - Internal: added an automated test suite for the holidays service (`test:holidays`) covering cache lookup with date-overlap, layer-toggle and subdivision filtering, sync caching/idempotency, and country/region listing against a mocked OpenHolidays API. No user-facing or runtime behavior change. ## [0.67.0] - 2026-06-09 ### Added - Public & school holidays calendar layer powered by the free [OpenHolidays API](https://openholidaysapi.org) (no API key required). Under **Settings → Calendar**, an admin picks a country and optional state/region, sets the layer colors, and syncs; holidays are then cached locally and shown as a read-only overlay across the month, week, day, and agenda views. Each layer (public holidays / school holidays) has its own show/hide toggle in the calendar toolbar. The auto-sync scheduler keeps the cache current across the previous, current, and next two years, and outbound requests carry only the country/region code — no household data leaves the server. ### Fixed - Calendar month view now loads events, tasks, and holidays for the leading days of the grid (the trailing days of the previous month shown in the first week), which were previously outside the fetched date range. ## [0.66.6] - 2026-06-09 ### Fixed - Backup files are now named `yuvomi-backup-.db` instead of the pre-rebrand `oikos-backup-…`. This applies to scheduled backups, the WebDAV "Upload now" snapshot, and the admin database download. Existing `oikos-backup-…` files (local and on WebDAV) continue to be listed and rotated, so older backups are not orphaned after the rename. ## [0.66.5] - 2026-06-09 ### Fixed - Unraid Community Applications: removed the leftover `oikos.xml` template, which carried the same `Yuvomi` (and the same `ghcr.io/ulsklyc/yuvomi` image) as the current `yuvomi.xml`. The duplicate name caused a conflict in the Community Apps feed; `yuvomi.xml` is now the single, authoritative Unraid template. ## [0.66.4] - 2026-06-09 ### Fixed - Sidebar navigation is now consistently aligned: the brand logomark and the icon wells of all nav items share the same horizontal center axis, the active/hover indicator pill is inset as a floating shape and vertically centered within its item, and the logo header has a fixed height so it no longer jumps when collapsing or expanding the sidebar. ## [0.66.3] - 2026-06-09 ### Fixed - WebDAV "Upload now" now creates a fresh, uniquely timestamped backup of the current database and uploads that, instead of re-uploading the latest existing local backup under its original filename. Manual uploads no longer overwrite the previous remote backup, so each trigger adds a distinct file (subject to the configured keep limit). ## [0.66.2] - 2026-06-09 ### Security - Avatar color selection now uses `crypto.randomInt` instead of `Math.random` (CWE-338). ## [0.66.1] - 2026-06-09 ### Fixed - Deactivated kitchen modules (Meals, Recipes, Shopping) no longer appear as sub-tabs in the Kitchen view; clicking Kitchen now navigates to the first enabled kitchen module instead of looping back to the dashboard. - Dashboard "Today" cockpit cards for disabled modules are now hidden. - Dashboard widgets for disabled modules are no longer rendered. - Settings navigation icon now displays a gear/cogwheel instead of a sun shape. - Sidebar logo and navigation icon wells are now pixel-aligned on the horizontal center axis. ## [0.66.0] - 2026-06-09 ### Changed - Renamed the project from **Oikos** to **Yuvomi** to avoid a trademark conflict with an unrelated product of the same name. The app name, documentation, GitHub Pages and deploy descriptors now read Yuvomi — your existing data and settings are fully preserved on upgrade. - The Docker image moved to `ghcr.io/ulsklyc/yuvomi`. The previous `ghcr.io/ulsklyc/oikos` image keeps publishing for a couple more releases so existing deployments keep working — please update your image reference at your convenience. - The repository moved to `https://github.com/ulsklyc/yuvomi`; existing `ulsklyc/oikos` links (clone URLs, raw assets, releases) redirect automatically. ## [0.65.34] - 2026-06-08 ### Added - Vietnamese (`vi`) translation — all UI strings are fully localized, including the web installer wizard and CLI installer. - VND (Vietnamese Đồng) added to the supported currencies list in Settings → Budget. ## [0.65.33] - 2026-06-08 ### Fixed - The avatar color picker now resets to a fresh random color after each member is added or the form is cancelled, preventing all subsequent members from receiving the same color as the first. ## [0.65.32] - 2026-06-08 ### Fixed - The `rrule()` validator now uses the full anchored `RRULE_RE` pattern instead of an unanchored prefix check, preventing malformed rules like `FREQ=YEARLYX` or `FREQ=YEARLY;INTERVAL=abc` from passing validation. ## [0.65.31] - 2026-06-08 ### Fixed - New family members created via the admin panel, from a contact in split expenses, or as a split guest now receive a random color from the avatar palette instead of always defaulting to blue. The new-member form in Settings also pre-populates the color picker with a random palette color. ## [0.65.30] - 2026-06-08 ### Fixed - Tasks and calendar events with a **yearly** recurrence rule (`FREQ=YEARLY`) were rejected by the server with "invalid recurrence rule". The server-side `rrule()` validator now accepts `YEARLY` in addition to `DAILY`, `WEEKLY`, and `MONTHLY`. ## [0.65.29] - 2026-06-08 ### Added - Desktop sidebar is now collapsible: a toggle button folds the navigation down to icon-only mode (56 px). Labels, the brand name, and the section heading are hidden; icons and tooltips remain. The collapsed state is persisted in `localStorage` and restored on reload. Toggling animates smoothly via the existing CSS width and margin transitions. ## [0.65.28] - 2026-06-08 ### Added - Avatar upload now shows an interactive **crop dialog**: drag to pan, zoom with the slider or mouse wheel, then confirm to save a 256 × 256 px square crop. Works for profile pictures and housekeeping staff avatars. ## [0.65.27] - 2026-06-08 ### Added - README badges for TrueNAS SCALE, Unraid, and Umbrel with links to their respective app store pages. ### Fixed - Shopping list: swipe-affordance chevron (›) no longer overlaps the delete button on desktop — the chevron hint is now hidden at ≥1024 px where the explicit delete button is used instead. ## [0.65.26] - 2026-06-08 ### Changed - README module icons now use each module's accent color with white icon strokes at 64×64 px, matching the visual style of the GitHub Pages landing page. ## [0.65.25] - 2026-06-08 ### Fixed - README module icons now render correctly — replaced blank PNGs (produced by a failed qlmanage render) with proper images generated via sharp. ## [0.65.24] - 2026-06-08 ### Security - Escape `req.url` before embedding it in the mock WebDAV XML response in tests (CodeQL `js/reflected-xss` alert #14). ## [0.65.23] - 2026-06-08 ### Fixed - README Modules table icons are now visible on GitHub — switched from SVG to PNG to work around GitHub's CSP restriction on raw.githubusercontent.com SVG files. ## [0.65.22] - 2026-06-08 ### Changed - README Modules table now uses SVG icons instead of emojis, matching the visual style of the GitHub Pages landing page. ## [0.65.21] - 2026-06-08 ### Added - **WebDAV backup target** — after each automatic local backup, Oikos can now upload the file to any WebDAV-compatible server (Nextcloud, ownCloud, Hetzner Storage Box, Infomaniak kDrive, etc.). Configure in **Settings → Backup → WebDAV Backup Target** or via six new environment variables (`WEBDAV_BACKUP_ENABLED`, `WEBDAV_BACKUP_URL`, `WEBDAV_BACKUP_USERNAME`, `WEBDAV_BACKUP_PASSWORD`, `WEBDAV_BACKUP_PATH`, `WEBDAV_BACKUP_KEEP`). Environment variables take precedence over the UI configuration and make fields read-only. Uses Node 22 built-in `fetch` — zero new npm dependencies. Upload failures are non-fatal: the local backup is always retained. Password is always masked (`****`) in the API and UI. - Manual "Upload now" button in Settings → Backup to trigger an immediate WebDAV upload of the latest local backup file. - "Test connection" button with inline success/failure feedback. - Remote backup rotation: oldest remote files are deleted automatically once the configured `keep` limit is exceeded. ## [0.65.20] - 2026-06-08 ### Added - Calendar events are now **coloured by their assignee's avatar colour**. When a single user is assigned the event background uses their avatar colour; when multiple users are assigned a diagonal CSS gradient (135 °) blends all their colours in equal segments. Events without assignees continue to use the manually set event colour, the calendar's colour, or a neutral grey fallback. - The event colour picker is visually disabled (greyed out with a hint text) while an assignee is set, reflecting that the assignee colour takes priority. Removing all assignees re-enables the picker. - Added `colorOverriddenByAssignee` i18n key to all 18 supported locales. ## [0.65.19] - 2026-06-08 ### Added - Assigned-user avatars now appear on the **Upcoming Events** dashboard widget, consistent with the Tasks widget. Each event card shows a stacked avatar row (profile photo if set, coloured initials otherwise) on the right side of the card. ## [0.65.18] - 2026-06-08 ### Changed - README redesigned as a visual landing page: stats bar (14 modules, 18 languages, 0 trackers, AES-256, MIT), side-by-side desktop + mobile PWA hero screenshot, six-module screenshot gallery with dark/light mode support, emoji-icon module table, structured NAS platform table (TrueNAS SCALE, Umbrel, Unraid), and Podman added to the tech stack badge row. ## [0.65.17] - 2026-06-08 ### Added - Weather settings now include a **"Detect location"** button that uses the browser Geolocation API to auto-fill latitude and longitude; a Nominatim reverse-geocoding call (OpenStreetMap, no API key required) also populates the optional city field on success. ## [0.65.16] - 2026-06-07 ### Fixed - Creator avatar and name in note cards are no longer tinted by the note's background color. The footer's `opacity: 0.55` (which cascades to all children including the avatar) has been replaced with `color: color-mix(in srgb, currentColor 55%, transparent)`, which mutes the border and text while leaving the avatar image and background-color at full opacity. ## [0.65.15] - 2026-06-07 ### Fixed - Loading screen ("Oikos" spinner) is now correctly centered on desktop viewports. Previously, `.app-loading` shrank to its content width when `.app-shell` switched to `flex-direction: row` at ≥1024 px, pushing the spinner to the far left. ## [0.65.14] - 2026-06-07 ### Fixed - Family member widget avatars in the dashboard are now circular (`border-radius: var(--radius-full)`) instead of square with small rounded corners (`--radius-sm`), matching the consistent round avatar style used throughout the app. ## [0.65.13] - 2026-06-07 ### Fixed - Android PWA scroll freeze: touch gestures starting on non-scrollable elements (card headers, separators, empty backgrounds) no longer lock the touch sequence. Added `touch-action: pan-y` to `.app-content` so Android Chrome correctly identifies the scroll container from the start of the gesture, without propagating through `body { overflow: hidden }`. ## [0.65.12] - 2026-06-07 ### Fixed - Sidebar navigation items no longer get an unintended pill shape (`border-radius: full`) on desktop hover. The glass hover rule in `glass.css` was global and applied `--radius-glass-chip` to all nav items; narrowed to `.nav-bottom .nav-item` so sidebar items keep their intended `--radius-sm` (8px) from `layout.css`. ## [0.65.11] - 2026-06-07 ### Fixed - Frontend audit test for mobile bottom navigation now checks the correct CSS selector (`.nav-item__label` instead of `.nav-bottom .nav-item__label`); the `line-height: 1.2` rule lives on the shared label class after a prior CSS consolidation, so the test was failing on CI despite the property being correctly applied. ## [0.65.10] - 2026-06-07 ### Fixed - Navigation labels no longer clip descenders (e.g. 'g', 'p', 'y') in the sidebar. `line-height: 1` was too tight, cutting letters at the baseline with `overflow: hidden`; raised to `1.2`. ## [0.65.9] - 2026-06-07 ### Fixed - Weather widget icons now remain visible in light mode. SVG stroke was bound to `var(--color-text-secondary)` (dark in light mode) against the widget's always-dark gradient background; changed to `currentColor` so it inherits `var(--color-text-on-accent)` from the parent. ## [0.65.8] - 2026-06-07 ### Fixed - Dashboard tasks widget now renders all assigned users instead of only the first assignee. The server payload includes the full `assigned_users` array via the `task_assignments` join, and the client renders it with the shared `renderAvatarStack` component. ## [0.65.7] - 2026-06-07 ### Added - "Install anywhere" platform showcase on the GitHub Pages landing page, featuring Docker, Podman, TrueNAS, Umbrel and Unraid with inline brand logos and one-click badges. - Umbrel and Unraid documented as installation options in the README and the installation guide; the install page now covers all six methods (Web Installer, Docker image, build from source, TrueNAS, Umbrel, Unraid). ### Changed - GitHub Pages landing page (`docs/index.html`) and installation page (`docs/install.html`) fully rebuilt with a brand-aligned design: self-hosted Plus Jakarta Sans replacing the Google Fonts CDN, the app's warm-neutral palette with violet and per-module accent colors, a Liquid-Glass-meets-editorial look, refined light/dark themes, and reworked EN/DE copy. - Landing page restructured with a new hero, feature showcase, 14-module grid, screenshot carousel, platform section and expanded footer. ## [0.65.6] - 2026-06-07 ### Changed - Screenshots refreshed across all platforms: web screenshots now target iPad Pro 13" (2752 × 2064 px) and mobile screenshots target iPhone 17 Pro Max portrait (1320 × 2867 px). - Demo user Linda added to the screenshot seed with a profile picture and English locale; Dortmund weather configured. - Split-expenses module added to the screenshot set (light + dark × web + mobile). - Unraid Community Apps gallery composites rebuilt against the new web and mobile sources. - Umbrel gallery images (1–5.jpg, 1440 × 900) replaced with current screenshots. - GitHub Pages (`docs/index.html`) updated to reference the renamed `-web.png` files. - Screenshot script (`scripts/take-screenshots.mjs`) fully automated: seeds demo data, creates Linda user via API, starts an isolated server, and captures all 14 modules in both themes. ## [0.65.5] - 2026-06-07 ### Fixed - Dashboard no longer shows a stray accent-colored frame around the content area on first load. The main content region is programmatically focused after navigation (a skip-link accessibility pattern); on the initial load the browser treated this as `:focus-visible` and drew a 2px inset outline around the whole content area, which vanished after the first module switch. The non-interactive region focus target no longer renders a visible outline. ## [0.65.4] - 2026-06-07 ### Fixed - Umbrel Catalog Publish workflow: the "Resolve multi-arch image digest" step ran under `set -euo pipefail`, so the first `docker buildx imagetools inspect` miss (image not yet published) tripped `set -e` and aborted the 40× retry loop after ~2s instead of waiting for the image. The command substitution now tolerates a transient miss (`|| true`), so the loop retries as intended. ## [0.65.3] - 2026-06-07 ### Security - Documented the Umbrel first-run exposure: with the Umbrel reverse-proxy auth disabled (`PROXY_AUTH_ADD: "false"`), Oikos's unauthenticated bootstrap endpoint that creates the first admin is reachable by any LAN/Tor client until setup is completed. Added a caveat to `deploy/umbrel/docker-compose.yml` and the Umbrel README advising owners to finish setup immediately after install. ## [0.65.2] - 2026-06-07 ### Security - Hardened the Open-Meteo weather test's upstream URL assertion to parse the URL and match the exact host (`api.open-meteo.com`) instead of a substring check, resolving a CodeQL "incomplete URL substring sanitization" alert (CWE-20). ## [0.65.1] - 2026-06-07 ### Fixed - Dark mode: white text and icons sat on light accent and semantic fills — the floating action button, delete/danger buttons, notification badges, completion checkmarks, active filter chips, and the calendar "today" markers were nearly illegible. They now use a dark ink color in dark mode, restoring WCAG AA contrast (the toast pattern, generalized to a shared `--color-ink-on-vivid` token). ### Changed - Replaced the colored left-border accent stripes on list rows and cards (tasks, shopping, budget, contacts, notes, housekeeping) with full borders and background tints, matching the design system and improving visual consistency across modules. - Page titles and the dashboard greeting now use fixed type-scale steps instead of fluid sizing; the greeting is no longer oversized on large screens. ## [0.65.0] - 2026-06-07 ### Added - New **Open-Meteo** weather provider for the dashboard widget — free, ECMWF-backed, and requiring no API key. Set your location with the new `WEATHER_LAT`, `WEATHER_LON`, `WEATHER_CITY`, and `WEATHER_UNITS` environment variables, or configure it in-app under Settings → Weather (admin only); the in-app setting takes precedence and activates Open-Meteo automatically. - Weather conditions now render as Lucide icons with localized descriptions (WMO weather codes) across all 18 languages. ### Changed - The setup installer's weather step now asks for Open-Meteo coordinates (latitude/longitude, optional city, units) instead of an OpenWeatherMap API key. - OpenWeatherMap remains supported as a legacy provider: existing `OPENWEATHER_*` configurations keep working and are used automatically when no Open-Meteo location is configured. ## [0.64.2] - 2026-06-07 ### Fixed - Checking or unchecking an item in a long shopping list no longer scrolls the list back to the top — only the affected row is updated instead of re-rendering the whole list, so your scroll position is preserved while shopping (#276). ## [0.64.1] - 2026-06-07 ### Removed - Removed the obsolete TrueNAS catalog generator and its `truenas-publish` release workflow. The community catalog now updates entirely through the published `ghcr.io` images, which TrueNAS's own bot picks up automatically — the local generator no longer delivered anything and failed on every release. The TrueNAS app config source (`deploy/truenas/questions.yaml`, compose) is retained. ## [0.64.0] - 2026-06-07 ### Added - Kazakhstani Tenge (KZT) is now selectable as a currency in the global household settings and the Split Expenses module (#272). ## [0.63.7] - 2026-06-07 ### Fixed - API-token requests (`Authorization: Bearer `) no longer crash with a 500 error when creating budget transactions, loans, loan repayments, notes, tasks, shopping lists, meals, or recipes. Affected routes read the canonical authenticated user id (`req.authUserId`) instead of the session-only `req.session.userId`, which is undefined for token auth (#270). ## [0.63.6] - 2026-06-06 ### Changed - Module page headers (Tasks, Notes, Housekeeping, Documents, Calendar) now share a single `.page-toolbar` shell, giving every module the same header height, spacing, sticky behaviour, and title typography so the head no longer shifts when switching modules. The Documents header is now sticky and uses the standard page background like every other module. ## [0.63.5] - 2026-06-06 ### Changed - Dashboard corner radii now use shared design tokens instead of hardcoded pixel values, with two new scale endpoints (`--radius-2xs`, `--radius-2xl`) for consistent rounding across the design system. - The housekeeping empty state now uses the shared `.empty-state` component, matching the look of empty states in other modules. ## [0.63.4] - 2026-06-05 ### Fixed - Filter chip remove buttons now display a properly centred Lucide `x` SVG icon instead of a `×` text character, which was rendered off-centre due to font metrics (#265). ## [0.63.3] - 2026-06-05 ### Added - The meal planner now supports **multiple items per slot**: each day/meal-type cell can hold any number of meals, displayed as stacked cards with a separator. A hover-visible `+` button lets you add another item to an already-filled slot without opening a different view (#262). ## [0.63.2] - 2026-06-05 ### Fixed - The calendar event popup was semi-transparent (`rgba(255,255,255,0.70)`) due to the `--glass-bg-card` token, making text hard to read over colourful calendar content. Changed to `--color-surface` (fully opaque) (#252). ## [0.63.1] - 2026-06-05 ### Fixed - Input fields in the Settings page (and throughout the app) were missing their visible border. `glass.css` was overriding `.form-input` `border-color` with `--glass-border-subtle`, which resolves to `rgba(255,255,255,0.35)` in light mode — effectively invisible on white backgrounds. Changed to `--color-border` (#253). ## [0.63.0] - 2026-06-05 ### Added - Workers can now use either a **daily flat rate** or an **hourly rate** (`rate_type = 'hourly'`) (#239). The worker form has a rate-type selector; check-out computes `minutes_worked` from the session duration, rounds to the nearest 15 minutes, and stores the resulting amount. The visit editor shows a live recalculation preview when adjusting worked minutes. - Decay tasks (recurring chores) can now be **edited, deleted, and undone** directly from the chore list (#244). Undo clears `last_completed`, resetting the urgency indicator to "not yet done". - Housekeeping visits can be **edited from the dashboard** (recent-visits strip) and **from the calendar** — tapping a housekeeping calendar event opens the visit editor via a deep-link (`?editVisit=`) (#245). - Staff accounts (users with a `housekeeping_workers` row) are now **hidden** from task-assignment pickers, dashboard member avatars, and the family contact list; their birthday entries remain visible in the calendar and birthday list (#243). ### Security - Accounts linked to a housekeeping worker row are now **blocked from logging in** (#243). The login endpoint returns HTTP 403 for such accounts, preventing staff from accessing family data. ## [0.62.4] - 2026-06-05 ### Fixed - CalDAV outbound sync now generates RFC 5545-compliant datetime strings. Previously, `parseTimeInput` returned `HH:MM` (no seconds), and the ICS builder produced a 4-digit time (`HHMM`) instead of the required 6-digit `HHMMSS` format. Strict CalDAV servers such as mailbox.org rejected the invalid value and defaulted the event time to 00:00 (#246). - All-day events synced to CalDAV now use `DTSTART;VALUE=DATE` and an exclusive `DTEND` per RFC 5545, instead of being treated as timed events at midnight (#246). - Outbound CalDAV ICS now includes `DTSTAMP`, `LOCATION`, and `RRULE` fields, and handles missing `end_datetime` gracefully (#246). ## [0.62.3] - 2026-06-05 ### Fixed - Date input fields now reject letter keystrokes at the keyboard level, so only digits and the separators `.`, `/`, and `-` can be typed in date fields. Time input fields allow digits, `:`, space, and AM/PM characters (`a`, `p`, `m`). Modifier-key combinations (Ctrl, Cmd, Alt) pass through unblocked. Applies to task, calendar, meal-plan, and recurrence-rule date/time inputs (#242). - Typing a bare hour (e.g. `15` or `9`) in a time field now expands automatically to a full time on blur: `15:00`, `09:00`. Previously only `HH:MM` and `H:MM AM/PM` formats were accepted (#242). - Typing an 8-digit date string without separators (e.g. `09062026`) is now accepted in date fields and formatted according to the locale date preference (DMY → `2026-06-09`, MDY → `2026-09-06`, YMD → `2026-06-09`) (#242). ## [0.62.2] - 2026-06-05 ### Fixed - The Google sync-target picker now lists only writable calendars (accessRole `owner` or `writer`). Read-only calendars (`reader`, `freeBusyReader`) no longer appear as outbound destinations, preventing 403 errors when saving events. If an existing event already targets a calendar that has since become read-only, the picker re-inserts that option non-destructively so saving the event does not silently reset its target to "Local". The server-side outbound sync also guards against writing to a calendar that lost write permission after the event was created. ## [0.62.1] - 2026-06-05 ### Fixed - Changing an event's start date in the calendar dialog now moves the end date by the same number of days, preserving the event's duration. Previously the end date stayed put, so moving the start into the future could leave the end on an earlier day and the event was saved with an end before its start. Saving an event whose end is before its start is now rejected with a clear message. ## [0.62.0] - 2026-06-05 ### Added - Sync and display **multiple Google calendars** at once (#237). After connecting Google, admins enable each available calendar individually via checkboxes in Settings → Synchronization; enabled calendars are imported together, each in its own color and with its own incremental sync token. Disabling a calendar removes its imported events and clears its token, so re-enabling performs a clean full resync. An automatic migration carries any previously single-selected Google calendar into the new model, so existing installs keep syncing without reconfiguration. ### Changed - The event dialog now has a single unified **sync target** picker that lists the enabled Google and CalDAV calendars plus "Local only", replacing the CalDAV-only target dropdown (#237). Outbound sync to Google is now per-event: a local event is pushed to Google only when an explicit Google calendar target is selected — events without a target stay local. This changes the previous behaviour where new events were auto-uploaded to the single configured calendar. The global Google read-only mode still overrides any per-event target. ### Removed - The single-calendar `PUT /api/v1/calendar/google/calendar` endpoint, replaced by `PATCH /api/v1/calendar/google/calendars` for enabling/disabling individual calendars (#237). ## [0.61.1] - 2026-06-05 ### Fixed - The CalDAV calendar selected under "Sync to CalDAV" when creating or editing an event is now persisted (#241). The create and update endpoints previously dropped `target_caldav_account_id` and `target_caldav_calendar_url`, so the selection reset to "Local" after saving and the event was never synced to the CalDAV server. Invalid account IDs are now rejected with a 400 instead of being silently ignored. ## [0.61.0] - 2026-06-05 ### Added - Recurring budget entries can now use an interval (monthly, half-yearly, yearly) and optional **virtual budgeting** (#240). With virtual budgeting on, a large infrequent bill is smoothed evenly across the months — e.g. a 1,200/year insurance shows as 100/month in the monthly summary, balance and CSV export instead of a single lump in one month. Without it, the full amount posts only on its due months. Existing recurring entries keep their previous behaviour (monthly, full amount). ## [0.60.11] - 2026-06-04 ### Fixed - `SESSION_SECURE` now defaults to `false` so that direct HTTP deployments (TrueNAS, bare Docker, Podman without a reverse proxy) work out of the box. Previously the default was `true`, which caused login to return 200 but every subsequent request to return 401 because the browser silently dropped the `Secure` cookie over plain HTTP. Set `SESSION_SECURE=true` in your `.env` when running behind an HTTPS reverse proxy (Caddy, Nginx, Traefik). Docker Compose and Podman Compose deployments are unaffected — all Compose files already injected `SESSION_SECURE=false` via `${SESSION_SECURE:-false}` and continue to behave identically. ## [0.60.10] - 2026-06-04 ### Added - Add read-only mode for Google Calendar sync (#236). A new checkbox in Settings → Synchronization → Google Calendar lets admins prevent Oikos from pushing local events back to Google Calendar while still reading incoming events normally. The flag is stored in `sync_config` and cleared automatically when the Google Calendar connection is disconnected. ## [0.60.9] - 2026-06-04 ### Fixed - Start Oikos directly as the assigned user when the container is launched as a non-root user. The entrypoint switched to the `node` user with `gosu`, which only works when the container starts as root, so platforms that run the container under a fixed non-root user (and chown the volumes with a separate init step) could not start Oikos. The entrypoint now only fixes ownership and drops privileges when running as root, and otherwise runs directly as the assigned user. Normal Docker and Docker Compose deployments are unaffected. ## [0.60.8] - 2026-06-04 ### Fixed - Create and fix ownership of the `/backups` and `/app/modules` volumes inside the container. The Docker image only prepared `/data`, so when `/backups` and `/app/modules` were mounted as named volumes they stayed owned by root and the app's `node` user could not write backups or read installed modules. The container's permission fix now also skips itself gracefully when the container is started as a non-root user, which keeps it compatible with orchestrators that manage volume ownership themselves. ## [0.60.7] - 2026-06-04 ### Added - Add Czech (cs) as the 18th supported language (#234). Czech-speaking families can now use Oikos fully translated, including the web installer wizard and CLI installer. ## [0.60.6] - 2026-06-03 ### Added - Add Dutch (nl) as the 17th supported language (#231). Dutch-speaking families can now use Oikos fully translated, including the web installer wizard and CLI installer. ## [0.60.5] - 2026-06-03 ### Fixed - Dashboard overview now shows today's calendar events throughout the day (#230). Events with a start time earlier than the current time were filtered out of the upcoming-events widget, so users with morning appointments saw "no events today" from noon onward. The widget now includes all events from midnight of the current day. ## [0.60.4] - 2026-06-03 ### Security - Fix a regular-expression denial-of-service (ReDoS) in the ICS calendar parser (CodeQL #10). The parameter-list patterns matching `DUE`/`DTSTART` lines allowed catastrophic backtracking on a crafted line containing many `;` separators without a closing colon, which could freeze the server while parsing a malicious subscribed or imported calendar. The inner character class is now restricted so the separator and parameter content no longer overlap. - Apply the API rate limiter to the admin-only `/docs` and `/openapi.json` endpoints (CodeQL #11, #12). Both routes live outside the rate-limited `/api/` path and were previously unthrottled. ### Fixed - Keep the time of day for tasks whose `DUE` value uses `VALUE=DATE-TIME`. A word boundary in the date-only detection also matched `VALUE=DATE-TIME`, so timed reminders imported via CalDAV/ICS were truncated to their date and lost their time. ## [0.60.3] - 2026-06-03 ### Security - Restrict the OpenAPI specification (`/openapi.json`, `/api/v1/openapi.json`) and the `/docs` documentation page to signed-in admins, based on a penetration-test scan (#228). `/docs` is now hidden entirely in production and returns `404` unless the new optional `ENABLE_API_DOCS=true` is set, in which case it is exposed to admins only. - `GET /api/v1/version` now returns the exact application version only to authenticated callers (session or API token). Unauthenticated login and setup pages still receive `app_name` and `setup_required`, so version fingerprinting no longer works anonymously. - `POST /api/v1/auth/setup` responds with `404` instead of `403` in production once initial setup is complete, so the first-run admin-creation flow is no longer confirmed to anonymous visitors. - Remove the deployment host URL and SQLite implementation details (backup endpoint descriptions, version schema) from the generated OpenAPI spec. ## [0.60.2] - 2026-06-03 ### Fixed - Show multi-day events as a single continuous span instead of repeating them on each day (#225). A multi-day timed event (e.g. the 14th 03:00 → the 19th 08:05) was placed on every day of its range and each view used the raw start/end clock times, so it appeared as an identical `03:00–08:05` block on every day rather than one event spanning the whole window. Multi-day events are now rendered in the all-day row of the week and day views (reading as a continuous bar across the days), and the agenda view shows per-day segment labels (`from {time}` on the start day, `all day` on the middle days, `until {time}` on the end day). ## [0.60.1] - 2026-06-03 ### Fixed - Show recurring calendar events on the Overview page (#224). The dashboard used a simplified upcoming-events query that filtered on the event's master `start_datetime` without expanding recurrence rules, so a recurring series whose first occurrence was in the past never appeared on the Overview — even though it showed correctly on the Calendar page. This made calendar items look like they were missing for specific family members. The dashboard and `/calendar/upcoming` now share the same recurrence-aware logic (`server/services/calendar-events.js`), including ICS visibility filtering. ## [0.60.0] - 2026-06-03 ### Added - Sync Apple Reminders into Tasks and Shopping via CalDAV (#218). Apple Reminders lists are CalDAV collections whose supported components include `VTODO`. Reusing the existing CalDAV accounts, an admin can now discover an account's reminder lists in Settings → Synchronization, enable individual lists, and map each one to either the Tasks or the Shopping module. Enabled lists are mirrored **read-only** (iCloud → Oikos) on each sync: reminders become tasks or shopping items keyed on their remote UID, completed reminders are reflected as done/checked, due dates and priorities are imported, and items removed from a list are pruned locally. Migration 45 adds the `caldav_reminder_selection` table and `external_uid`/`external_source`/`external_account_id` columns to `tasks` and `shopping_items`. ## [0.59.0] - 2026-06-03 ### Added - Choose which Google calendar to sync. Google Calendar sync was previously hardcoded to the `primary` calendar, forcing families whose shared calendar is not their primary one to restructure their Google setup. After connecting, an admin can now pick the calendar to sync from a dropdown in Settings → Synchronization. The selection defaults to `primary` for existing installs; switching calendars resets the incremental sync token and re-imports events from the newly selected calendar. ## [0.58.2] - 2026-06-03 ### Fixed - Preserve user-assigned event colors for Google Calendar events across syncs. The sync no longer overwrites a manually chosen event color on every refresh — the Google calendar color is now only used as the default when an event is first imported. The calendar and dashboard views also prioritize the event color over the calendar color, so color categories assigned to synced events are displayed correctly. ## [0.58.1] - 2026-06-03 ### Fixed - Fix Google Calendar outbound sync failing for timed and recurring events. Oikos stores timed events without seconds (`YYYY-MM-DDTHH:MM`), but the Google Calendar API requires RFC 3339 datetimes with seconds — timed events were rejected with "Bad Request" and recurring events surfaced the malformed start as "Invalid recurrence rule". Outbound events now emit seconds, and recurrence `UNTIL` values are coerced to the type Google requires: a plain DATE for all-day events and a UTC date-time for timed events. ## [0.58.0] - 2026-06-03 ### Added - Web-based first-run setup: create the first admin account directly in the browser on a fresh install. The first visit detects that no account exists, walks you through a setup form (username, display name, password with confirmation), creates the admin, and signs you in automatically — localized in all 16 interface languages. The `node setup.js` CLI remains available as a headless fallback. ### Changed - The public version endpoint now reports whether first-run setup is still required, so the app routes new installations to the setup page automatically and back to login once an admin exists. - Hardened the first-run setup endpoint against concurrent requests: the user-count check and the admin insert now run in a single transaction, so two simultaneous first-run submissions can no longer create two admin accounts. ## [0.57.7] - 2026-06-03 ### Fixed - Make the weather widget follow the app language, support city IDs, and key its cache per city/units/language. - Fix janky, laggy scrolling in tall modals (e.g. the event editor) caused by a backdrop-filter on the scroll container. ### Changed - Scope icon re-rendering to changed subtrees and index calendar day lookups for smoother large lists and month views. - Debounce the documents and split-expenses search inputs. - Add database indexes for event/task assignment, loan-payment, and recurring-event lookups. - Batch split-expense detail loads to remove an N+1 query and sort dashboard tasks in SQL. - Back global search with an FTS5 full-text index instead of full-table LIKE scans. - Compress CSS/JS/JSON responses with gzip and defer the icon library so it no longer blocks first paint. ## [0.57.6] - 2026-06-03 ### Fixed - Unraid Community Apps template: the Overview section incorrectly told new users to "open the WebUI and create your admin account." Oikos has no web-based first-run signup — the first admin is created via `node setup.js` in the container Console, as documented in the README and installation guide. The template now matches the actual bootstrap flow. ## [0.57.5] - 2026-06-03 ### Fixed - Google Calendar sync: all-day events imported from Google no longer show an extra day. Google Calendar stores exclusive end dates per RFC 5545 (a 2-day event Jan 1–2 has `end.date = "2026-01-03"`); Oikos was storing this value as-is, making every multi-day event appear one day longer than it actually is. - Google Calendar sync: recurring events with an end date no longer fail to sync to Google with "Invalid recurrence rule." The outbound mapping was sending the recurrence rule without the required `RRULE:` prefix, which Google's API rejects. Both the missing prefix and the incorrect (non-exclusive) all-day end date in the outbound payload are now fixed. ## [0.57.4] - 2026-06-02 ### Changed - Refined the Unraid Community Apps template: the `Registry` link now points to the browsable GitHub Container Registry package page, and added `ExtraSearchTerms` so Oikos is easier to find in the Community Apps store. ## [0.57.3] - 2026-06-02 ### Fixed - Login page now stays centered on desktop browsers. Before the first login no sidebar exists, but at viewports ≥1024px the app shell still switched to its sidebar row layout, which collapsed the sidebar-less login wrapper to its content width and pinned it to the left — making the desktop login look like the mobile layout. The shell now stays in column flow while the login page is mounted, so the form is fully centered again. ## [0.57.2] - 2026-06-02 ### Changed - Moved all `test-*.js` suites from the project root into a dedicated `test/` directory and updated every reference (npm `test:*` scripts, the browser test loader, and test imports of app and root files). No runtime or user-facing behaviour changes; `npm test` is unchanged. ## [0.57.1] - 2026-06-02 ### Changed - Updated `openid-client` to v6. This is an internal rewrite of the OIDC/SSO implementation; the four `OIDC_*` environment variables and the login flow are unchanged (the client-secret token-endpoint authentication method is preserved). Minor bumps to `googleapis` and `puppeteer`. ### Security - Resolved a transitive denial-of-service advisory in the `qs` dependency (GHSA-q8mj-m7cp-5q26). ## [0.57.0] - 2026-06-02 ### Added - The CLI installer (`install.sh`) is now fully localized into all 16 supported languages, matching the web installer. It auto-detects the language from the shell environment (`OIKOS_INSTALLER_LANG` > `LC_ALL` > `LC_MESSAGES` > `LANG`) and accepts a `--lang ` override. Translations live in per-language `tools/installer/locales/cli/.sh` files — `en` is the fallback base, the active language overlays it. ## [0.56.0] - 2026-06-02 ### Added - Podman support for RHEL-based distributions (RHEL, Fedora, CentOS Stream, Rocky, Alma): a dedicated `podman-compose.yml` adds the SELinux `:Z` volume relabel so rootless containers can access their data, and exposes a configurable `OIKOS_HTTP_BIND` host bind address (default `0.0.0.0`). - `tools/quadlet/oikos.container` — a systemd Quadlet unit for rootless Podman autostart, with `EnvironmentFile`, `:Z` volumes, the same healthcheck as Compose, and boot persistence via `loginctl enable-linger`. - Both the web installer and the CLI installer now auto-detect the container engine, preferring Docker and falling back to `podman compose` (Podman 4.1+) or `podman-compose`. ### Changed - Web and CLI installers route every container command (start, inspect, logs, prerequisite checks) through the detected engine instead of a hard-coded `docker`; with Podman they use `podman-compose.yml` automatically. - Documentation (README, installation guide, SPEC, MODULES, installer README, and the GitHub Pages landing/install pages) now covers the Podman/SELinux install path, the new `OIKOS_HTTP_BIND` variable, and rootless systemd autostart. ## [0.55.19] - 2026-06-02 ### Added - Installer wizard is fully localized into all 16 supported languages with automatic browser-language detection, via its own `tools/installer/locales/*.json` and `i18n-mini.js` (mirrors the app's locale resolution; `de` is the reference, `en` the fallback). - New optional "Advanced" installer step covering reverse-proxy/HTTPS deployments (sets `SESSION_SECURE`/`TRUST_PROXY`), Single Sign-On (OIDC), and automatic backups — all configurable without hand-editing `.env`. - Installer verifies Docker prerequisites before the wizard starts and surfaces container start/spawn errors in the UI instead of failing silently. - `GET /api/preflight` reports whether an existing `.env` file and a running `oikos` container are present. ### Changed - Installer adopts the app's design language: shared design tokens and Plus Jakarta Sans (violet accent, matching radii/shadows, automatic dark mode), served read-only from the repo. - Installer wizard now meets WCAG 2.1 AA — keyboard-operable accordion buttons (`aria-expanded`/`aria-controls`), `role="alert"` error banners, a live `role="status"` Docker-status region, focus moved to the active step heading on navigation, labelled password-visibility toggles, a step counter derived from the step list, and a unified error-banner style. - `docker-compose.yml` maps the chosen host port (`${OIKOS_HTTP_PORT:-3000}:3000`) and derives `SESSION_SECURE` from `.env` (`${SESSION_SECURE:-false}`), so reverse-proxy setups take effect without manual edits; default `3000`/`false` behaviour is unchanged. ### Fixed - Installer persists the user-selected timezone (`TZ`) and HTTP port (`OIKOS_HTTP_PORT`) to `.env` so the choices actually take effect; `install.sh` gains the same fields for CLI parity. - Installer backs up an existing `.env` to `.env.bak-` before overwriting, so re-runs no longer destroy an existing configuration; `install.sh` does the same. ### Security - Hardened installer `.env` writing against injection: keys are allowlisted against the shared env schema and values containing newlines are rejected. ## [0.55.18] - 2026-06-02 ### Changed - Installer env configuration extracted into a shared `tools/installer/env-schema.js` module (`ENV_SCHEMA`). Adds `TZ` and `OIKOS_HTTP_PORT` fields (both with `writeToEnv: true`) and a `group` field per entry. `GET /api/defaults` now serves `ENV_SCHEMA` directly; existing UI behaviour is unchanged. ## [0.55.17] - 2026-06-02 ### Changed - **Documentation synced with changelog v0.45.0–v0.55.16:** `SPEC.md` adds `oidc_sub`/`oidc_provider` columns to the Users table and documents the SSO login flow (Authorization Code + PKCE, nonce) and failed-login warning logging; `docs/installation.md` adds `TRUST_PROXY` to the Server section, `DATA_DIR`/`BACKUP_DIR` to the Database section, a new SSO/OIDC env-var section, a new Automated Backups env-var section, and a legacy note on the Apple CalDAV single-account variables; `README.md` adds SSO/OpenID Connect to the Design & Technology section; `docs/index.html` updates the version badge and footer to v0.55.16 and corrects the birthday feature description to mention customizable reminders; `docs/install.html` updates the Calendar Sync optional card to reflect multi-account CalDAV/CardDAV, adds an SSO/OIDC optional card, updates the Automated Backups card to describe the built-in scheduler, and keeps EN and DE i18n strings in sync. ## [0.55.16] - 2026-06-02 ### Fixed - `TRUST_PROXY` environment variable is now parsed correctly: numeric values like `1` are treated as a hop count (not an IP address), so `req.ip` returns the real client IP when running behind a reverse proxy such as Traefik or nginx. Subnet strings (e.g. `172.16.0.0/12`) and named values (`loopback`) continue to work as before. - `.env.example` documents `TRUST_PROXY` with examples for Traefik/Docker setups. ## [0.55.15] - 2026-06-01 ### Fixed - Failed login attempts are now logged as warnings with IP address, username, and failure reason (`user_not_found` or `invalid_password`), enabling fail2ban/CrowdSec integration. ## [0.55.14] - 2026-06-01 ### Added - OIDC/SSO single sign-on support via any OpenID Connect provider (Authentik, Keycloak, Google, etc.), configurable through four environment variables (`OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, `OIDC_REDIRECT_URI`). - Authorization Code flow with PKCE (S256) and nonce for secure SSO; state, nonce, and code verifier are stored in the session and consumed once. - Login page shows an "Sign in with SSO" button only when OIDC is configured; displays a localised error message on failed SSO attempts. - Database migration v42 adds `oidc_sub` and `oidc_provider` columns to the `users` table with a partial unique index. - SSO i18n keys (`loginWithSso`, `orDivider`, `ssoError`) added to all 16 supported locales. ## [0.55.13] - 2026-06-01 ### Fixed - Fixed Polish locale offline availability by including `pl.json` in the service worker locale precache and expanded frontend locale audits to cover dynamic keys, `labelKey` usage, and `data-i18n` attributes. ## [0.55.12] - 2026-06-01 ### Fixed - Fixed unresolved frontend translation keys so the PWA install prompt and other UI labels render localized text instead of raw key names. ## [0.55.11] - 2026-06-01 ### Changed - **Documentation refreshed for the completed frontend UI/UX audit rollout:** Updated the README, GitHub Pages copy, product specification, audit notes, and landing-page design docs to reflect the stronger work surfaces, mobile ergonomics, stable Kitchen/More navigation identity, Calendar readability improvements, Settings information architecture, and current release version. ## [0.55.10] - 2026-06-01 ### Changed - **Frontend UI/UX audit rollout completed:** Refined the visual foundation with stronger work surfaces and quieter Liquid Glass treatment, improved mobile dashboard readability, consolidated dense Tasks and Shopping controls, and kept Kitchen/More navigation identity stable across desktop and mobile. - **Calendar readability improved across views:** Month cells now have clearer boundaries, today emphasis, stronger event/task chips, readable agenda rows, tokenized all-day labels, and Lucide metadata icons instead of visible emoji markers. - **Settings information architecture tightened:** Added a sticky desktop settings navigation, mobile tab scroll affordances, keyboard-friendly shared sub-tabs, and accented cards for major admin, account, family, API token, and backup sections. - **Final accessibility and localization polish added:** Replaced remaining inline icon sizing in touched Calendar and Budget actions, kept Budget row actions touch-visible on mobile, improved More sheet focus restoration after navigation, and added regression coverage for locale key consistency. ## [0.55.9] - 2026-06-01 ### Changed - **Navigation identity and icon language tightened:** Kept Kitchen and More bottom-nav labels stable while exposing active subsections through localized accessible labels, replaced isolated inline SVG/icon sizing with Lucide placeholders and icon utility classes in the touched navigation, Kitchen, Shopping, and Settings surfaces, and added More active labels across all locales. ## [0.55.8] - 2026-06-01 ### Changed - **Mobile task and shopping controls refined:** Collapsed secondary task toolbar controls into a compact mobile overflow, kept bulk actions hidden until tasks are selected, and rebuilt the shopping quick-add row for clearer 390px touch ergonomics. ## [0.55.7] - 2026-05-31 ### Fixed - **Mobile dashboard readability improved:** Prevented first-viewport dashboard highlights from splitting German words mid-word, widened mobile cockpit cards, reserved space for the fixed FAB, and kept compact quick actions accessible. ## [0.55.6] - 2026-05-30 ### Changed - **Landing page feature showcase extended with Budget and Shopping rows:** Added two new alternating screenshot rows to `docs/index.html` — "No surprise at the end of the month." (Budget) and "The list everyone actually checks." (Shopping) — each with desktop and mobile screenshots. Both EN and DE locales included. ## [0.55.5] - 2026-05-30 ### Changed - **GitHub Pages landing page redesigned as a narrative marketing page:** Restructured `docs/index.html` from a feature-list into a problem→trust→solution flow targeting privacy-conscious families. Added Social Proof Bar (live GitHub star count, module count, language count, version), new "The Problem" section with three pain-point cards, and moved the Philosophy section up and renamed it "Why Oikos" with reordered cards (Privacy First → Self-Hosted → Open Source → Zero Build Step). Rewrote Hero copy ("Your family. Your data. Your home."), Feature-Showcase titles as benefit statements, and Feature-Grid trimmed to five priority cards. Simplified Setup section with a three-step visual overview and collapsible Docker command block. Updated CTA to three differentiated buttons (Get started, See all screenshots, View on GitHub). Added version, star count, and Install link to Footer. Both EN and DE locales updated throughout. ## [0.55.4] - 2026-05-30 ### Changed - **README redesigned as a professional landing page:** Replaced the dense feature table with a compact two-column module grid, promoted the desktop screenshot to a large hero image (800 px, dark/light adaptive), added a CTA row (Install · Screenshots · Docs) below the badges, refined the tagline to "The self-hosted family planner. Private, offline-capable, and beautiful.", added horizontal-rule section separators for visual rhythm, and replaced the Documentation pipe-table with an inline link row. ## [0.55.3] - 2026-05-30 ### Changed - **SPEC updated to v0.55.2:** Documents the Phase 7 Living Drifting Backdrop (`.lg-backdrop`, `--lg-*` tokens), Enter-submits-modal convention, modal state machine, and budget chart screen-reader summary. Version reference updated to v0.55.2. - **awesome-selfhosted description updated:** Now reflects CalDAV/CardDAV multi-account sync, split expenses, and housekeeping module. ## [0.55.2] - 2026-05-30 ### Fixed - **Mobile screenshots no longer have a gray bar at the bottom:** The screenshot script now uses a proportionally larger viewport (459×993) instead of CSS `zoom: 0.85` on the root element. CSS zoom shrinks content below the viewport height, leaving an empty gray strip; the larger viewport lets the app fill the frame naturally while still showing the equivalent of 85%-zoomed content. ## [0.55.1] - 2026-05-30 ### Fixed - **Kitchen pages no longer drift under the tab bar while scrolling:** The meal planner and recipes pages did not subtract the kitchen tab bar height from their viewport height, so the outer scroll container overflowed by exactly the tab bar height. On desktop this made the whole page (week navigation and the day header row, e.g. "MO") drift upward while scrolling instead of only the inner content. Both pages now reduce their height by the tab bar height, matching the shopping page, so only the inner grid scrolls and the day headers stick correctly. ## [0.55.0] - 2026-05-29 ### Added - **Screen-reader summary for the budget category chart:** The category bar chart now exposes a concise `.sr-only` summary (number of categories plus the largest category and its share) so assistive technologies can convey the data without parsing the purely visual bars. ### Changed - **Enter submits modal forms:** Pressing Enter in a single-line field inside a modal now submits the form (the standard web convention) instead of advancing focus to the next field. - **More robust modal lifecycle:** Reworked the shared modal into an explicit state machine (idle/open/confirming/closing) with encapsulated suspend/restore helpers, hardening the unsaved-changes confirmation against double-close and back-navigation races. Behavior is otherwise unchanged. ### Security - **Escaped modal titles and option labels:** Modal titles, `selectModal` option labels, and `promptModal` default values are now centrally HTML-escaped, closing an XSS vector where raw user-supplied text (e.g. a task title reused as a modal heading) was injected unescaped. ## [0.54.12] - 2026-05-29 ### Added - **UI/UX audit (May 2026):** Added `docs/UI-UX-AUDIT-2026-05.md` documenting a full review across mobile/desktop and light/dark mode with prioritized findings. ### Fixed - **PWA theme color mismatched the app accent:** The light-mode `theme-color` meta tag was a stale indigo (`#4F46E5`) while the actual app accent is violet (`#6c3aed`), so the installed PWA's status/address bar rendered a different hue than the UI. Aligned `theme-color` to the brand accent. - **Login page could overflow horizontally on desktop:** The login screen used `width: 100vw`, which includes the scrollbar width and produced a horizontal scrollbar / clipped edge whenever a vertical scrollbar was present. Switched to `width: 100%`. - **Sub-12px UI text raised to the 12px readability floor:** The desktop sidebar version label, sidebar section headings, and the reminder count badge still used a 10px font size, below the project's own 12px minimum. Raised them to 12px and aligned the reminder badge box to 18px to match the standard nav badge. ## [0.54.11] - 2026-05-29 ### Fixed - **Calendar – unreadable time-axis labels:** The week and day view time-axis labels used the disabled-text token (`--color-text-disabled`), which fell far below the WCAG AA 4.5:1 contrast ratio against the grid background (~1.2:1 in light mode, ~1.5:1 in dark mode). Switched to `--color-text-tertiary` for legible, AA-compliant times in both themes. - **Navigation – "Household" section label showed a raw key:** The desktop sidebar section heading rendered as `NAV.SECTION.HOUSEHOLD` instead of the translated label. The locale key was stored as a flat `"section.household"` string inside `nav`, but `t()` resolves dot-paths as nested objects, so it never matched and fell back to the (uppercased) key. Restructured the key to a nested `nav.section.household` object across all 16 locales. - **Meal plan & list headers scrolled under glass cards:** Sticky section headers in the meal plan (`.day-header`), calendar agenda (`.agenda-day__header`), and contacts list (`.contact-group__header`) sat on the base z-layer (`--z-base`), so translucent Liquid Glass cards rendered above them while scrolling. Raised them to `--z-sticky` so they stay on top. ## [0.54.10] - 2026-05-29 ### Added - **Liquid Glass – living drifting backdrop:** Added a `.lg-backdrop` layer with four blurred, slowly drifting color blobs behind the entire app shell — the "liquid" that the glass surfaces now refract. Blob 1 follows `--active-module-accent`, so the whole ambient subtly recolors per section (e.g. violet on Calendar, teal on Budget), while blobs 2–4 use fixed module tints (shopping, tasks, meals) for variety. The blobs live on the non-scrolling `.app-shell` (outside the `.app-content` scroll container), so they neither trigger nor are affected by the iOS/Android blank-screen mitigation (Issue #166). The drift animation honors `prefers-reduced-motion` (freezes), and `prefers-reduced-transparency` / `prefers-contrast: more` hide the backdrop entirely via tokens. - **Liquid Glass – design tokens:** Introduced five `--lg-*` tokens in `tokens.css` — `--lg-blob-opacity` (0.4 light / 0.55 dark, 0 in reduced-transparency/contrast), `--lg-glass-saturate`, `--lg-card-radius`, `--lg-density`, and `--lg-specular`. ### Changed - **Liquid Glass – stronger specular on elevated surfaces:** The sidebar and bottom navigation now carry an inset top-highlight driven by `--lg-specular`, per the canonical glass recipe, giving the elevated glass panels a crisper specular edge. ### Changed - **Calendar – week view time-slot click opens create-event modal:** Clicking an empty time slot in the week view time grid now opens the create-event modal again (reverts the day-view navigation introduced in v0.54.8). Navigating to the day view on time-slot clicks was too disruptive for users who intentionally tap a specific hour to create an event quickly. ## [0.54.8] - 2026-05-29 ### Changed - **Calendar – day navigation from month and week views:** Tapping a day cell in month view now navigates to the day view for that date instead of immediately opening the create-event modal. In week view, tapping a day header or an empty time-slot column likewise switches to the day view, allowing users to review the day's schedule before adding an event via the "+" button or by tapping a time slot in day view. ## [0.54.7] - 2026-05-29 ### Fixed - **Calendar – recurring event end time shifted by UTC offset:** When expanding recurring events server-side, `end_datetime` for each instance was computed via `.toISOString()`, which always appends a `Z` (UTC) suffix. Stored datetimes use no timezone marker (naive local-time strings), so browsers interpreted the `Z`-suffixed recurring instances as UTC — shifting displayed end times by the user's UTC offset (e.g. +2 h for UTC+2). The fix preserves the format of the original datetime: naive sources produce a timezone-free `YYYY-MM-DDTHH:MM` string; `Z`-suffixed sources (e.g. CalDAV imports) retain the ISO/UTC path. ## [0.54.6] - 2026-05-29 ### Fixed - **Calendar – event assignment for non-admin users:** The `GET /auth/users` endpoint previously required admin privileges, causing the assignee dropdown to silently render empty for child and other non-admin family profiles. Removed the unnecessary `requireAdmin` guard so all authenticated family members can load the user list and assign calendar events. ## [0.54.5] - 2026-05-28 ### Changed - **Liquid Glass – Documents & Split Expenses modules:** Migrated `documents.css` and `split-expenses.css` to Glass design tokens. Document folder browser (`.documents-folder-browser`), document cards (`.document-card`), document rows (`.document-row`), the drop zone (`.document-dropzone`) and its icon, the member picker (`.document-member-picker`), and the view toggle (`.documents-view-toggle`) all use `--glass-bg-card`, `--glass-border-subtle`, `--radius-glass-card`/`--radius-glass-inner`, and `--glass-shadow-*` tokens. Split summary cards (`.split-summary-card`) receive a subtle module-accent tint via `::after`. Split cards (`.split-card`), the groups panel (`.split-groups-panel`), group headers (`.split-group-header`), groups (`.split-group`), and participants (`.split-participants`) are migrated to corresponding Glass tokens. All `--shadow-*` → `--glass-shadow-*`, `--radius-md/lg` → `--radius-glass-card/inner/chip`, and `--color-surface` → `--glass-bg-card` replacements applied. ## [0.54.4] - 2026-05-28 ### Changed - **Liquid Glass – Meals & Recipes modules:** Migrated `meals.css` and `recipes.css` to Glass design tokens. The autocomplete dropdown (`.meal-modal__autocomplete`) now uses `--glass-bg-card`, `--glass-border-subtle`, `--radius-glass-inner`, and `--glass-shadow-md`. The drag-ghost card (`.meal-card--ghost`) uses `--glass-shadow-lg`. Ingredient rows (`.ingredient-row`) receive `--radius-glass-inner` for consistency. Recipe cards (`.recipe-card`) use `--radius-glass-card`, `--glass-bg-card`, `--glass-border-subtle`, and `--glass-shadow-sm`; a hover state adds `--glass-bg-card-hover` and `--glass-shadow-md`. Recipe ingredient rows (`.recipe-ingredient-row`) use `--radius-glass-inner`. `.meal-slot` was already migrated in `glass.css` §30 and is unchanged. ## [0.54.3] - 2026-05-28 ### Changed - **Liquid Glass – Housekeeping module:** Migrated `housekeeping.css` to Glass design tokens. Main cards (`.housekeeping-card`) use `--radius-glass-card`, `--glass-bg-card`, `--glass-border-subtle`, and `--glass-shadow-sm`. Inner elements (`.housekeeping-worker-strip`, `.housekeeping-metric`, `.housekeeping-task`, `.housekeeping-report-item`, `.housekeeping-staff-row`, `.housekeeping-staff-log-row`, `.housekeeping-template`, `.housekeeping-photo`, `.housekeeping-photo-preview`) use `--radius-glass-inner`. Interactive staff rows use `--glass-bg-card-hover` with module-accent tint on hover. The document-dropzone icon inside modals uses `--glass-shadow-sm`. ## [0.54.2] - 2026-05-28 ### Changed - **Liquid Glass – Settings module:** Migrated `settings.css` and `settings-nav.css` to Glass design tokens. Settings cards (`.settings-card`), CalDAV account items, module rows, and the settings sidebar now use `--glass-bg-card`, `--glass-bg-elevated`, `--radius-glass-card`/`--radius-glass-inner`, `--glass-border-subtle`, and `--glass-shadow-*` tokens. Interactive rows (`.toggle-row`, `.cat-row`, `.caldav-calendar-item`) use `--glass-bg-card-hover` on hover. Tooltips use `--glass-shadow-lg`. Sidebar navigation items use `--radius-glass-inner` with glass hover states. ## [0.54.1] - 2026-05-28 ### Changed - **Liquid Glass – Budget module:** Migrated `budget.css` to Glass design tokens. Summary cards (`.budget-summary-card`), the loans panel, individual loan cards, loan transactions, the loan report hero and grid cells, transaction entry hover states, and the inline modal panel now use `--glass-bg-card`, `--radius-glass-card`/`--radius-glass-inner`, `--glass-border-subtle`, and `--glass-shadow-*` tokens. Summary cards receive a subtle module-accent tint via `::after`. The overlay backdrop uses `--color-overlay-glass` instead of a hardcoded `rgba` value. ## [0.54.0] - 2026-05-28 ### Added - **Liquid Glass Navigation:** Sidebar and mobile bottom bar now feature a sliding glass pill indicator that animates to the active entry. - **Custom nav icons:** `public/nav-icons.js` provides a full set of monoline SVG icons for all navigation entries, built entirely with the DOM API (`createElementNS`) — no `innerHTML`. - **Desktop hover preview:** Hovering an inactive sidebar entry shows the destination indicator at 50 % opacity before navigation. - **Household section label:** A "Haushalt" section heading appears between the four primary entries (Dashboard, Calendar, Tasks, Notes) and the module entries in the sidebar. - **Locale key `nav.section.household`:** Added to all 16 supported locale files. - **Accessibility:** Navigation animations are suppressed when `prefers-reduced-motion` is active; glass effects are disabled when `prefers-reduced-transparency` is active. - Lucide icon fallback for any navigation entry that lacks a custom SVG. ## [0.53.1] - 2026-05-28 ### Removed - **pyAmortiza module:** Removed the bundled Brazilian mortgage calculator module from the repository; the module system remains fully functional for externally mounted modules. ### Fixed - `isIOSInstallFlow()` no longer returns `true` when the app is already running in standalone (installed PWA) mode, restoring the invariant that `getPwaInstallState()` never yields `{installed: true, ios: true}` simultaneously. ## [0.53.0] - 2026-05-27 ### Added - **Module system:** Runtime-loadable third-party modules discovered from a configurable `modules/` directory. Each module declares metadata via `module.json` and is validated server-side before being served. - **Admin module controls:** Admins can enable/disable individual modules and drag-to-reorder navigation entries in Settings → Modules. - **Dynamic SPA routing:** Enabled module pages are registered automatically in the router at startup without any code changes to the host app. - **Docker support:** Mount external modules via the `MODULES_DIR` environment variable. - **Example module — pyamortiza:** Brazilian mortgage amortization calculator bundled as a reference module implementation. - **PWA install utility:** `public/utils/pwa-install.js` centralises the install-prompt lifecycle; `oikos-install-prompt` component now imports from it. ### Fixed - Toast notifications in Settings used the unsupported type `'error'`; corrected to `'danger'` in five call-sites (CardDAV and meal-types sections). - `PUT /api/v1/preferences` now enforces an admin role check before processing `disabled_modules`; non-admin users receive a 403 response, preventing household-wide module changes. - `disableFailedThirdPartyModule` now attempts the API call first; on a 403 (non-admin user) the module remains visible in navigation rather than being silently removed. ## [0.52.58] - 2026-05-27 ### Added - **Task chips in Calendar:** Open and in-progress tasks with a due date now appear as priority-coloured chips in all four calendar views (month, week, day, agenda). Clicking a chip navigates directly to the task edit modal. Tasks with a due time show the time in the chip label. Done and archived tasks are not shown. ## [0.52.57] - 2026-05-26 ### Fixed - Restored colored inactive icon wells for the mobile Kitchen and More navigation buttons. ## [0.52.56] - 2026-05-26 ### Security - Updated helmet from 8.1.0 to 8.2.0 (adds `noopener-allow-popups` support for Cross-Origin-Opener-Policy). - Updated googleapis from 171.4.0 to 172.0.0 (optional dependency for Google Calendar sync; Calendar API v3 unaffected by breaking changes). ## [0.52.55] - 2026-05-25 ### Fixed - Improved mobile bottom navigation spacing with wider pill-shaped icon wells and more reliable label line-height to avoid clipped text on Android. ## [0.52.54] - 2026-05-25 ### Fixed - Allow task date fields to accept slash and hyphen separators when creating or editing tasks. ## [0.52.53] - 2026-05-25 ### Fixed - Mobile bottom navigation now reserves iOS safe-area space while keeping floating action buttons stable. - Mobile More search now uses a native button with visible keyboard focus styling and focuses immediately when the sheet opens. - SPA route changes now move keyboard focus to the main content after navigation while leaving login focus behavior untouched. ## [0.52.52] - 2026-05-25 ### Fixed - Mobile More navigation now closes reliably when choosing a route after locale or navigation rebuilds. ## [0.52.51] - 2026-05-25 ### Changed - Bottom navigation icon wells enlarged from 32 × 32 px to 36 × 36 px for a more prominent, touch-friendly appearance. - Icon well border-radius increased from `--radius-xs` (4 px) to `--radius-sm` (8 px) across all nav contexts, giving a softer squircle shape consistent with the More-sheet wells. ## [0.52.50] - 2026-05-25 ### Changed - Bottom navigation items now display colored icon wells (32 × 32 px rounded squares) matching the style of the "More" sheet, with per-module accent colors applied consistently across all six slots (primary items, Kitchen button, and More button). - Sidebar navigation items receive smaller icon wells (26 × 26 px) for visual consistency with the iOS-style sidebar pattern. - Kitchen and More buttons in the bottom bar dynamically adopt the active sub-module's accent color when a kitchen route or a secondary-sheet route is active. - More button default icon changed from `ellipsis` to `grid-2x2` to match the icon used when no secondary module is active. ## [0.52.49] - 2026-05-24 ### Changed - Dashboard stat icons (tasks, shopping, notes, budget) now render in their respective module accent colors instead of the generic dashboard color. - Today-overview cockpit cards carry a subtle accent-tinted background and border in their default (non-hover) state; hover state intensity increased for clearer affordance. - Cockpit card metric values are now rendered in the card's accent color for stronger visual hierarchy. - Icon wells (cockpit card icons and "More" navigation sheet items) now blend against `--color-surface-elevated` instead of transparent, and gain an inset specular highlight for a raised, glassy appearance. - Login page ambient background gains a third radial gradient blob and stronger top-glow opacity for more atmospheric depth. ## [0.52.48] - 2026-05-24 ### Changed - Module page content area now carries a subtle top radial gradient tinted with the active module accent color for atmospheric depth. - Bottom navigation active-item pill opacity raised from 14 % to 20 % and gains an inset specular highlight ring; global active nav-item background raised from 14 % to 18 %. - FAB entrance animation overshoots to scale 1.07 at 65 % before settling, duration extended to 0.42 s for a spring feel. - Interactive card hover lift increased from −2 px to −3 px with a fractional scale and a larger shadow. - Dashboard greeting title now scales fluidly from 18 px to 24 px via `clamp()` instead of a fixed size. ### Added - Login page gains a dual radial-gradient ambient glow in the accent violet instead of a flat background. ## [0.52.47] - 2026-05-24 ### Changed - Page titles now scale fluidly from 20 px to 30 px across viewport widths via `clamp()` instead of a hard breakpoint override. - App-shell ambient background gradients now correctly shift hue to match the active module color; a second gradient blob adds bottom-right depth. - Form input focus rings adopt the active module accent color instead of always using the default violet. - "More" navigation sheet items now render a colored rounded-square icon well tinted with each module's accent color. ### Fixed - App-shell background gradient was resolving to the fallback violet because it referenced `--module-accent` (scoped to child page elements) instead of `--active-module-accent` (set on `` by the router). ## [0.52.46] - 2026-05-24 ### Added - Frontend audit coverage now guards Phase 6 touch target sizing and localized bottom navigation label overflow regressions. ### Changed - Contact action buttons and shopping quick-add controls now use shared target-size tokens for consistent mobile touch sizing. ### Fixed - Long localized bottom navigation labels no longer create horizontal overflow on narrow mobile screens. ## [0.52.45] - 2026-05-24 ### Changed - Contacts now keep call and email actions prominent on mobile while moving export, maps, and delete into a compact overflow action so rows stay readable and safer to tap. - Documents and housekeeping empty states now guide setup with direct document, folder, and profile creation actions. - Budget category labels now normalize known raw category keys into localized display labels in charts and transaction metadata. ## [0.52.44] - 2026-05-24 ### Changed - Kitchen navigation now keeps a stable Kitchen label and utensils icon while announcing the active subpage through localized accessibility labels and the Kitchen tab bar. - More sheet search now hands off directly to global search with focus in the search input, avoiding a two-step-feeling transition. ## [0.52.43] - 2026-05-24 ### Changed - Tasks now keeps bulk actions hidden during normal list use, shows them only in bulk-select mode, and disables bulk buttons when no tasks are selected. - Shopping items can now be checked by tapping the row text area while preserving existing delete, input, select, and explicit button behavior. - Tasks, shopping items, and note pin/delete controls now use tokenized touch target sizing for more comfortable mobile interaction. ## [0.52.42] - 2026-05-24 ### Changed - Calendar now opens in Agenda view on first mobile load while preserving the user's selected calendar view after they change it. - Meals now presents a mobile-focused Today and next-days layout while keeping the full desktop week grid unchanged. ## [0.52.41] - 2026-05-24 ### Added - Swedish translations for tasks, settings, documents, and housekeeping modules. ## [0.52.40] - 2026-05-24 ### Added - Dashboard now starts with a compact Today cockpit that highlights the next urgent task, upcoming event, open shopping count, and planned dinner before the broader widget grid. ### Changed - First-run onboarding can now be skipped immediately from the first step, can be dismissed with Escape, and sits lower on mobile so the dashboard remains partially visible. ## [0.52.39] - 2026-05-24 ### Added - Frontend audit regression coverage now guards the accessibility and rendering fixes from this release: audited frontend files must not reintroduce `innerHTML` assignments, Meals and Budget must use local date keys, shared sub-tabs must wire tabs to panels, settings theme buttons must expose pressed state, and router overlays must stay hidden from keyboard focus when closed. - Shared local date helpers centralize YYYY-MM-DD generation for API payloads, week starts, and day arithmetic without relying on UTC ISO string slicing. ### Changed - More navigation and global search overlays now behave like proper dialogs: closed overlays are inert, open overlays declare modal semantics, focus moves into the active surface, Escape closes them, and focus returns to the launching control. - Shared sub-tabs now generate stable tab ids, connect each tab to its matching panel with `aria-controls` and `aria-labelledby`, and keep hidden panel state synchronized with the active tab. - Settings theme buttons now expose `aria-pressed` and update that pressed state whenever the active theme changes. - Shopping list creation now uses the existing localized label for its icon-only button instead of a hardcoded German ARIA label. - Notes, Meals, and the install prompt now render through `replaceChildren()`, `insertAdjacentHTML()`, or DOM APIs instead of assigning `innerHTML`, aligning these frontend paths with the project XSS policy. ### Fixed - Meals and Budget no longer derive today, week starts, or payment dates through UTC ISO slicing, preventing off-by-one calendar dates for users west of UTC and around local midnight. - The PWA install prompt now builds its dismiss icon with SVG DOM APIs and clears shadow content safely, avoiding blocked `innerHTML` assignments. - Hidden More and Search overlay controls are no longer reachable by keyboard or assistive technology while the overlays are closed. ## [0.52.38] - 2026-05-24 ### Fixed - Dashboard blank-screen on mobile scroll — keep the mobile bottom navigation stable on the Dashboard, stop mirroring scroll state onto ``, and remove scroll-time FAB and bottom-nav layout mutations that could trigger mobile WebKit/Blink compositor blanking. ## [0.52.37] - 2026-05-23 ### Fixed - Blank screen on scroll — disabled `filter` effects inside the `.app-content` scroll container to prevent mobile WebKit/Blink from promoting calendar/event elements into compositor layers during scroll, which can still trigger the empty-screen regression. ## [0.52.36] - 2026-05-23 ### Fixed - Dashboard blank-screen on scroll — removed `overflow: auto` from `.widget__body`, which created up to four nested scroll containers inside `.app-content` (one per task/event/birthday/shopping widget). iOS WebKit and Android Blink promote each `overflow:auto` child to its own compositor layer; multiple nested vertical scroll containers in one viewport trigger the blank-screen-on-scroll symptom even with `prefers-reduced-transparency: reduce` active, ruling out the earlier backdrop-filter and `color-mix` gradient theories. Widget content (3–7 list items) fits naturally; `.widget` already has `overflow: hidden` for rounded-corner clipping. ## [0.52.35] - 2026-05-23 ### Fixed - Dashboard blank-screen on scroll — new lead identified after the previous glass/gradient theories were ruled out by an iOS `prefers-reduced-transparency: reduce` test (bug persisted even with reduced transparency, so backdrop-filter and `color-mix` gradients are not the cause). Remaining differentiator: only the dashboard renders a `.fab-backdrop` element — a `position: fixed; inset: 0` full-viewport overlay that was always in the DOM (initial `opacity: 0`) so the FAB speed-dial open/close could cross-fade. iOS Safari and iOS PWA repeatedly composite fixed-positioned full-viewport elements per scroll frame, which is a known trigger for the blank-screen symptom in this exact scenario. Other module pages don't have this overlay and didn't reproduce the bug. Switched `.fab-backdrop` from `opacity: 0` + always-on `position: fixed; inset: 0` to `display: none` when inactive; only laid out when the FAB speed-dial is open. The opacity cross-fade is lost (was barely perceptible) but the dashboard scroll path no longer carries a permanent full-viewport fixed layer. ## [0.52.34] - 2026-05-23 ### Fixed - Dashboard blank-screen on scroll — actual dashboard-specific trigger identified. Each `.dashboard .widget::after` carried a `linear-gradient(135deg, color-mix(...), transparent 70%)` as a full-cover tint overlay (`glass.css` section 25). With many widgets stacked in the dashboard grid, each scrolling instance applied the gradient + `color-mix()` pattern repeatedly across the scroll viewport, reproducing the same WebKit/Blink scroll-rasterization failure that v0.52.32 fixed for `.app-content`. No other module page has a comparable per-card gradient overlay pseudo-element, which is why only the dashboard remained broken after v0.52.32/v0.52.33. Replaced the gradient with a flat translucent `color-mix()` background (half the original tint strength) so the module-accent vibrancy is preserved without a gradient. The pre-existing `@media (prefers-reduced-transparency: reduce) { .dashboard .widget::after { display: none } }` rule was a strong hint at the same conclusion. ## [0.52.33] - 2026-05-23 ### Fixed - Dashboard blank-screen on scroll — final remaining trigger. After v0.52.32 fixed the bug on every other page by moving the `color-mix()` radial gradient off the scroll container, the dashboard still reproduced the symptom because `.dashboard-overview` carried the same problematic pattern: a `linear-gradient(180deg, color-mix(...), color-mix(...))` on a large, scrolled element. Replaced with the solid `var(--color-surface)` background that all other `.widget` elements already use. The dashboard now matches the rest of the app: no scrolled element on any page carries a complex `color-mix()` gradient background. ## [0.52.32] - 2026-05-23 ### Fixed - Blank screen on scroll — sixth attempt, this time targeting the actual root cause. The radial `color-mix()` gradient on `.app-content` introduced in Liquid Glass Phase 4 was painted directly on the scroll container; WebKit (iOS Safari/PWA) and Blink (Android Chrome) both unreliably rasterize complex `color-mix()` gradients on `overflow:auto` elements during scroll, producing the empty-screen symptom on every page. Moved the gradient to `.app-shell` (viewport container, `height: 100dvh`, never scrolls); `.app-content` now has a transparent background so the gradient shows through unchanged. Visually identical, but no scrolling element carries a complex background. Why the five previous fixes (v0.52.22, v0.52.25, v0.52.27, v0.52.29, v0.52.30) failed: each targeted a different downstream symptom (sticky `backdrop-filter`, all `backdrop-filter` inside `.app-content`, `overflow: clip` on `.dashboard`, internal scroll container on the dashboard, `filter: saturate/drop-shadow` on widgets) under the assumption that many GPU compositor layers were the cause — but the bug reproduced on every page including pages without those triggers, and on Android, where the iOS-WebKit-compositor theory cannot apply. ## [0.52.31] - 2026-05-23 ### Fixed - Dashboard scrolling restored. The internal-scroll-container approach introduced in v0.52.29 (`display: flex; height: 100%; overflow: hidden` on `.dashboard`, `flex: 1; overflow-y: auto` on `.dashboard-shell`) caused a scroll regression: `height: 100%` on `.dashboard` resolved against `.page-transition` (its direct parent, `height: auto`), making it equivalent to `height: auto` per CSS spec. As a result `.dashboard-shell` received no height constraint and its `overflow-y: auto` never activated; on iOS, `overscroll-behavior-y: contain` on the unconstrained `.dashboard-shell` additionally blocked touch events from reaching `.app-content`. Fix: reverted to `overflow: visible` on `.dashboard` and removed the internal scroll container from `.dashboard-shell`; scrolling happens via `.app-content` as on every other page. ## [0.52.30] - 2026-05-23 ### Fixed - Dashboard scroll blank-screen fixed on iOS Safari and Android Chrome. Two `filter` properties on dashboard elements (`.event-item__bar { filter: saturate(0.4) }` and `.weather-widget__icon { filter: drop-shadow(...) }`) created GPU compositor layers inside the scroll container that overwhelmed the mobile compositor on both WebKit and Blink. Replaced `filter: saturate(0.4)` with `opacity: 0.5`; removed the drop-shadow filter entirely. The gap between content and bottom nav introduced in v0.52.29 is also fixed: `height: calc(100dvh - nav - safe-areas)` double-subtracted the nav height (`.dashboard` is already inside `.app-content` which excludes the nav), changed to `height: 100%`. ## [0.52.29] - 2026-05-23 ### Fixed - Dashboard no longer goes blank when scrolling on iOS Safari/WebKit (root cause fix). The real cause was that the dashboard was the only page scrolling via `.app-content`; on scroll, `initNavHideOnScroll` applied `transform: translateY(100%)` to `.nav-bottom` which—combined with its `backdrop-filter`—created an iOS 26 WebKit compositor conflict with the active scroll container. Fixed by giving `.dashboard` an internal scroll container (`.dashboard-shell`, analogous to all other pages), so `.app-content` never scrolls and the nav transition is never triggered. `initNavHideOnScroll` updated to use document-level capture scroll delegation and additionally listens to `#dashboard-shell`. Closes #166. ## [0.52.28] - 2026-05-23 ### Fixed - Scrolling on Notes, Contacts, Calendar, and Shopping pages no longer causes a blank screen on iOS Safari and mobile Chrome. `overflow: clip` on the page containers (`.notes-page`, `.contacts-page`, `.calendar-page`, `.shopping-page`) inside the `overflow: auto` scroll container triggered the same iOS WebKit compositor bug fixed for the dashboard in v0.52.27. Changed to `overflow: hidden`, which clips identically without the compositor regression. Closes #166. ## [0.52.27] - 2026-05-23 ### Fixed - Dashboard page no longer goes blank when scrolling on iOS (Safari, WebKit). `overflow: clip` and `isolation: isolate` set by an older skin variant on `.dashboard` were not reset when the Admin Dashboard Layout replaced it; `overflow: clip` inside an `overflow: auto` scroll container prevents WebKit from repainting scroll content, leaving only compositor-promoted elements (the dashboard-overview top border) visible. Both properties are now reset to their initial values. ## [0.52.26] - 2026-05-23 ### Fixed - Scrolling on any page no longer causes a blank/white screen on iOS (Safari, WebKit) and Android (Chrome, Blink). The previous partial fix (v0.52.22) only removed `backdrop-filter` from sticky toolbars; the root cause was broader — `glass.css` applied `backdrop-filter` to task cards, note items, dashboard widgets, form inputs, meal slots, group-toggles, and skeleton loaders inside the `overflow:auto` scroll container, each becoming a separate GPU compositor layer that overwhelmed the mobile compositor on scroll. A single permanent CSS rule now disables `backdrop-filter` for all scroll-container children; the bottom navigation bar, modals, and toasts retain their blur effect as they sit outside the scroll container. Closes #166. ## [0.52.25] - 2026-05-23 ### Added - Kitchen nav button (bottom bar and sidebar) now dynamically shows the icon and label of the last visited kitchen section (Meals / Recipes / Shopping), making the navigation target predictable at a glance - Offline banner now pushes page content down via `--offline-banner-height` CSS variable, preventing content overlap when the app is offline - `.grid--2` responsive grid now activates at 600 px instead of 768 px, giving iPad Mini portrait and small tablets a two-column layout ### Changed - Dashboard greeting text and date label refresh automatically on `visibilitychange`, so "Good Morning" no longer persists into the afternoon on a long-running session - FAB entry animation counter is now tracked per module instead of globally; the animation reappears when visiting a module for the first time even after it was suppressed on other modules - Icon size system consolidated from 8 granular sizes to 4 semantic steps — `icon-sm` (12 px), `icon-md` (16 px), `icon-lg` (20 px), `icon-xl` (24 px); old class names kept as backward-compat aliases - Document, budget loan, and budget loan payment deletions now use an optimistic undo-toast pattern (5 s window) instead of a blocking confirmation dialog, consistent with Tasks, Notes, and Contacts ## [0.52.24] - 2026-05-23 ### Changed - Dashboard widget accent bar is now muted (`color-mix` at 40% saturation) so multiple module colours no longer clash on the widget grid - Base body font size increased from 15 px to 16 px (`--text-base: 1rem`) for better desktop readability - Recurring-event weekday buttons enlarged from 40 px to 44 px (Apple HIG minimum) on screens narrower than 1024 px; day-grid uses `space-between` layout to fit all 7 days ### Fixed - Onboarding overlay no longer shows the "Skip" button on the first step or the last step, reducing premature dismissal before the navigation explanation is seen ## [0.52.23] - 2026-05-23 ### Fixed - Scrolling on mobile Safari (iOS 26+) and narrow-viewport browsers no longer causes the entire page to go blank. Root cause: `backdrop-filter` on `position:sticky` elements inside an `overflow:auto` scroll container triggers a WebKit compositor bug that blanks the whole scroll container. Fixed by removing `backdrop-filter` from all sticky toolbars (Tasks, Notes, Contacts, Calendar, Housekeeping, Shopping list headers) and `.sticky-header`, replacing semi-transparent glass backgrounds with an opaque `var(--color-bg)`. ## [0.52.22] - 2026-05-23 ### Added - `.gitattributes` added to enforce LF line endings for shell scripts and normalize all text files, preventing shebang breakage in Linux containers when the repo is cloned on Windows ## [0.52.21] - 2026-05-21 ### Added - Global search now includes contacts (matched by name, phone, email) and shopping items (matched by name); clicking a result navigates directly to the respective module - Contacts search results deep-link via `?open=` and open the edit modal immediately on page load - Shopping search results deep-link via `?list=&highlight=`: the correct list tab is activated and the matched item is scrolled into view - Calendar search results deep-link via `?open=` and open the event edit modal immediately on page load ### Fixed - Calendar search results previously navigated to `/calendar` without identifying the specific event; results now carry the event id and open the edit modal directly - Replaced all `innerHTML` assignments in `calendar.js`, `contacts.js`, and `shopping.js` with `replaceChildren()` and `insertAdjacentHTML` to comply with the project XSS policy ## [0.52.20] - 2026-05-21 ### Fixed - Dashboard skeleton screen now renders all 9 widgets with correct grid-spanning sizes (matching `DEFAULT_WIDGET_CONFIG`) instead of 6 fixed-width placeholders, preventing content layout shift on initial load ## [0.52.19] - 2026-05-21 ### Fixed - FAB no longer floats in the middle of the screen when the bottom navigation bar hides on scroll; it now animates to the bottom edge in sync with the nav bar and returns when the nav reappears ## [0.52.18] - 2026-05-21 ### Changed - Dashboard metric tiles now always display in a 2-column grid on all screen sizes; the single-column layout below 768 px has been removed, reducing the scroll offset on mobile by approximately 200 px ## [0.52.17] - 2026-05-20 ### Changed - Desktop sidebar now shows labels and the app name at 1024 px and wider (previously icon-only between 1024–1279 px); the collapsed icon-only range has been removed ## [0.52.16] - 2026-05-20 ### Changed - Notes is now a primary bottom navigation item (index 4), replacing it in the More-Sheet; the bottom bar order is now Dashboard → Calendar → Tasks → Notes → Kitchen → More - More-Sheet item count reduced from 7 to 6 by promoting Notes to the primary navigation bar - Tapping the search bar in the More-Sheet now closes the sheet instantly (no slide-out animation) before opening the search overlay, eliminating the jarring double-animation sequence ## [0.52.15] - 2026-05-20 ### Fixed - Toast notifications for success and default messages no longer interrupt screen reader output immediately; only danger and warning toasts use `aria-live="assertive"`, while success and default use `aria-live="polite"` - Removed redundant `role="listitem"` attribute from navigation `` elements; the parent container already provides list semantics, and the duplicate role was confusing assistive technologies ## [0.52.14] - 2026-05-20 ### Fixed - Dashboard metric titles now use 12 px (`--text-xs`) instead of 10 px (`--text-2xs`), satisfying WCAG 2.1 minimum text size - Login form now includes a password visibility toggle (eye/eye-off icon) so users can verify what they are typing before submitting ## [0.52.13] - 2026-05-20 ### Fixed - ICS text fields (SUMMARY, DESCRIPTION, LOCATION) now have RFC 5545 escape sequences unescaped on import; characters like `\,`, `\;`, `\n`, and `\\` are now displayed correctly instead of shown as raw backslash sequences - When pushing events to a CalDAV server, SUMMARY and DESCRIPTION values are now properly escaped per RFC 5545, preventing corrupted data on round-trip - CalDAV calendar names now appear correctly in the event edit modal's sync target dropdown; the dropdown was reading `calendar.url` and `calendar.display_name` instead of the API response fields `calendarUrl` and `calendarName`, causing empty or undefined entries ## [0.52.12] - 2026-05-20 ### Fixed - Settings page is accessible again after the v0.52.10 update; a missing closing parenthesis on the `insertAdjacentHTML` call in `settings.js` caused a JavaScript syntax error that prevented the entire settings page from loading ## [0.52.11] - 2026-05-20 ### Added - Tasks can now have a **start date**: tasks with a future start date are hidden from the list by default, reducing cognitive load for children and family members who should focus on current assignments only - A "Show scheduled" toggle chip in the task filter bar lets parents and admins see all upcoming planned tasks - Future tasks display a "Starts on …" badge in the task card so the scheduled date is always visible at a glance - All 16 UI languages include translations for the new start date field and filter toggle ### Changed - Replaced all remaining `innerHTML` assignments in `tasks.js` with `replaceChildren` / `insertAdjacentHTML` to comply with the project's XSS-safety constraint ## [0.52.10] - 2026-05-20 ### Fixed - CalDAV calendar names are now displayed correctly in Settings > Synchronization; the frontend was reading `cal.url`, `cal.display_name`, and `cal.color` instead of the API response fields `calendarUrl`, `calendarName`, and `calendarColor`, which caused blank calendar entries and an error when toggling a calendar's enabled state - Replaced remaining `innerHTML` assignments in `settings.js` with `replaceChildren` / `insertAdjacentHTML` to comply with the project's XSS-safety constraint ## [0.52.9] - 2026-05-19 ### Changed - Bumped better-sqlite3 to 12.10.0, express-rate-limit to 8.5.2, and tsdav to 2.2.2 - Bumped puppeteer (dev dependency) to 25.0.4 ## [0.52.8] - 2026-05-18 ### Fixed - Pinned notes on the dashboard now render Markdown formatting (bold, italic, lists) instead of displaying raw Markdown syntax ## [0.52.7] - 2026-05-16 ### Fixed - Bottom navigation bar is no longer invisible on mobile; `bottomNav.appendChild(bottomItems)` was accidentally dropped during the split-guest refactor in v0.52.6 ## [0.52.6] - 2026-05-16 ### Fixed - Split-guest users on mobile no longer see a broken Kitchen button and an empty More sheet that covered page content; those nav elements are omitted entirely for guest accounts - Converted `renderError` and toast icon rendering from `innerHTML` to DOM API to comply with the project's XSS-safety constraint ## [0.52.5] - 2026-05-13 ### Fixed - Translate `backupCliHint` string into 10 missing locales (ar, el, es, fr, hi, it, ja, ru, tr, zh) ## [0.52.4] - 2026-05-13 ### Added - Yearly recurrence option in the calendar event repeat dropdown (`FREQ=YEARLY`), with translations in all 16 supported locales ## [0.52.3] - 2026-05-12 ### Added - Complete Ukrainian (uk) localization: all previously untranslated strings in tasks, shopping, meals, calendar, housekeeping, budget, contacts, settings, reminders, documents, and onboarding are now fully translated (contributed by @baragoon) ## [0.52.2] - 2026-05-12 ### Fixed - Regenerated all PWA icon assets (`favicon.ico`, `favicon-32.png`, `icon-192.png`, `icon-512.png`, `icon-maskable-192.png`, `icon-maskable-512.png`, `apple-touch-icon.png`) from `docs/logo.svg` so they show the correct violet gradient (`#8b5cf6` to `#6c3aed`) matching the brand colors in `tokens.css` ## [0.52.1] - 2026-05-12 ### Changed - Bump `express-rate-limit` from 8.5.0 to 8.5.1 - Bump `tsdav` from 2.2.0 to 2.2.1 (fixes CalDAV compatibility with servers that omit `supported-calendar-component-set`) - Bump `puppeteer` from 24.42.0 to 24.43.1 ## [0.52.0] - 2026-05-11 ### Added - **Bike icon**: added `bike` icon to the calendar event icon selector (transport category), with translations for all 16 supported locales. ## [0.51.0] - 2026-05-11 ### Added - **Split Expenses module**: new tab inside Budget for managing shared expenses. Supports expense groups (household, couple, travel, event, shopping, general) with multiple split methods: equal, percentage, exact amounts, and shares. Balances are derived from an immutable ledger — amounts are stored as integer minor currency units (cents) to avoid floating-point errors. - **Settlements**: record payments between group members with a debt-simplification algorithm that produces the minimal set of transfers to clear all balances. - **Recurring expenses**: define expenses that repeat on a daily, weekly, monthly, or yearly schedule with automatic generation via an hourly scheduler. - **Guest accounts**: invite people outside the family as restricted guests who can only access the Split module and see their own invited groups. Guests can be created from scratch or converted from existing contacts. - **Multi-currency support**: each group has a default currency; individual expenses can use any currency with historical exchange rate snapshots for consistent balance reporting. - **Activity feed**: per-group log of all expense, member, and settlement events. - **Polish locale**: split-expenses strings added to the Polish (`pl`) translation. ## [0.50.0] - 2026-05-08 ### Added - **Polish locale**: full Polish (`pl`) translation added, covering all UI strings across all modules (tasks, calendar, shopping, meals, budget, notes, contacts, birthdays, recipes, documents, housekeeping, settings, and more). Polish is now selectable in Settings → Language. ## [0.49.0] - 2026-05-08 ### Added - **Housekeeping module**: new dedicated module for managing household staff workflows. Features include staff profiles (with avatar, daily rate, calendar color, payment schedule), work session check-in/check-out (with automatic local calendar event creation), recurring chore tracking with urgency decay indicators, supply requests (linked to shopping lists), and a monthly visit log with payment summaries. - **Document folders**: documents can now be organized into custom folders. A "Hausreinigung" folder is auto-created when a housekeeping worker is first added. - **Calendar icon picker**: calendar events now support a custom icon selected from a curated set of Lucide icons. - **Payment task integration**: each housekeeping check-in can optionally create a payment task; completing the task marks the visit as paid. Toggle in Settings → Haushaltshilfe. ### Changed - **Documents page**: added a folder browser sidebar and folder filter; existing documents without a folder remain accessible under "Alle Ordner". - **Dashboard**: housekeeping widgets show today's open sessions and upcoming chores. - **Settings**: new "Haushaltshilfe" section for the payment task toggle. - **Navigation**: housekeeping module appears in the main nav with Violet accent theming. ## [0.48.3] - 2026-05-06 ### Changed - **Brand color**: reverted the primary accent color from Amber back to Violet. The accent is now `#6c3aed` in light mode and `#a78bfa` in dark mode, applied consistently across all design tokens, the logo, all PWA icons (favicon, app icons, maskable icons, Apple touch icon), and the GitHub Pages documentation site. Semantic colors (warnings, notes module, meal-breakfast) remain unchanged. ## [0.48.2] - 2026-05-06 ### Changed - **Brand color refresh**: The primary accent color has been updated from cool indigo (`#4F46E5`) to a rich, warm amber (`#92400E` in light mode, `#FBBF24` in dark mode) across all design tokens, the logo, and the GitHub Pages documentation site. **Why this change?** Indigo carried the aesthetic of a productivity tool — focused, corporate, digital. As Oikos has grown into a home for thousands of families, we wanted the visual identity to better reflect what the app actually is: a warm, shared space for everyday life together. Amber — deep and earthy in light environments, bright and inviting in dark ones — communicates exactly that. It evokes warmth, reliability, and the kind of unhurried intimacy that family life deserves. From an accessibility standpoint, Amber-800 (`#92400E`) achieves a contrast ratio of 7.20:1 against white, exceeding the WCAG AA threshold and meeting WCAG AAA. The dark mode value (`#FBBF24`) maintains the same readability standard. The transition is purely cosmetic — no data, settings, or behavior has changed. - **Logo**: updated the gradient on `docs/logo.svg` and all inline SVG instances from violet (`#8B5CF6` to `#6C3AED`) to amber (`#B45309` to `#92400E`). ## [0.48.1] - 2026-05-06 ### Fixed - **Settings**: CalDAV and CardDAV "Add Account" modals now correctly display Cancel and Save buttons. Previously, the `onSave` callback ran immediately on modal open, triggering a required-fields validation error against empty fields and leaving the form with no way to submit. ## [0.48.0] - 2026-05-06 ### Added - **Multi-person assignment**: tasks and calendar events can now be assigned to multiple family members simultaneously. A new `task_assignments` / `event_assignments` join table (migration v32) stores the assignments; existing single-user data is migrated automatically. - **Avatar stack**: task cards, Kanban cards, and the calendar agenda view display stacked avatars for all assigned users (up to 3 visible, then a `+N` overflow badge). - **Shared UserMultiSelect component** (`public/components/user-multi-select.js`): checkbox-based dropdown used in both the task modal and the calendar event modal; replaces the previous single-user `