# 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.17.0] - 2026-04-13 ### Added - Design system: `public/styles/glass.css` - new additive layer (~430 lines) implementing Liquid Glass aesthetics: translucent surfaces, `backdrop-filter` blur, capsule shapes, specular highlights, and spring-based motion; loaded globally after `layout.css`, all blur effects gated behind `@supports (backdrop-filter: blur(1px))` - Design system: Section 16 "Glass Tokens" added to `tokens.css` - ~50 new custom properties covering `--glass-bg*`, `--glass-border*`, `--blur-xs/sm/md/lg/xl`, `--opacity-glass-*`, `--glass-highlight*`, `--glass-shadow-sm/md/lg`, `--radius-glass-card/inner/chip/button`, `--ease-glass`, `--transition-glass`; full dark mode overrides in both `@media (prefers-color-scheme: dark)` and `[data-theme="dark"]` blocks - Navigation: bottom bar now auto-hides on scroll-down (mobile only, < 1024px), reappears on scroll-up with 4 px hysteresis; implemented via `initNavHideOnScroll()` in `router.js` and `.nav-bottom--hidden` CSS class in `glass.css`; `will-change: transform` on `.nav-bottom` for smooth GPU-composited animation - Animations: modal entrance uses spring easing (`glass-modal-scale-in` + `glass-sheet-in` keyframes) instead of linear fade; page transitions use spring-eased translate instead of plain ease-out; list items stagger with spring `cubic-bezier(0.34, 1.56, 0.64, 1)` spring curve - Accessibility: `prefers-reduced-transparency`, `prefers-reduced-motion`, and `prefers-contrast: more` media query blocks in both `tokens.css` and `glass.css` - glass effects deactivate and solid fallbacks activate automatically ### Changed - Glass input styles: `.contacts-toolbar__search-input`, `.notes-toolbar__search-input`, and `.quick-add__input` now use `--radius-glass-button`, `--glass-border-subtle`, and a `color-mix` focus ring for visual consistency with the glass layer (applied directly in module CSS files to respect CSS load order) - Bottom nav / sidebar: glass blur surface, subtle top highlight, elevated shadow via `glass.css` - Modal: glass overlay, spring entrance, capsule close button, specular FAB ring pulse (`fab-ring-pulse` keyframe) - Buttons / FAB: capsule shape via `--radius-glass-button`, specular inner highlight on primary buttons, glass hover glow on secondary - Skeleton loading: upgraded shimmer gradient uses glass highlight colors - Focus rings: animated expand-contract ring via `glass-focus-ring` keyframe, applied to interactive glass elements - PWA viewport: `maximum-scale` changed from `1` to `5` (WCAG 1.4.4 - Resize Text, users can pinch-zoom again) - Theme color meta tag: `#007AFF` → `#2563EB` (light) and `#1C1C1E` → `#222220` (dark) to match updated token palette ### Fixed - Accessibility: `--color-text-tertiary` corrected from `#737370` to `#6B6B68` (passes WCAG AA 4.5:1 on `--color-bg`) - Accessibility: `--color-info` corrected from `#54AEFF` to `#0969DA` (passes WCAG AA 4.5:1 on white) - Accessibility: modal overlay now carries `aria-label` and `role="presentation"` for correct screen-reader semantics - Settings: fixed three stale token references (`--color-background` → `--color-bg`, `--duration-fast` → `--transition-fast`, `--color-surface-raised` → `--color-surface-2`) - Notes: fixed stale token reference `--color-text` → `--color-text-primary` in search input border - Dashboard: weather widget gradient now uses `var(--color-accent-deep)` instead of hardcoded `#1E5CB3` - Meals: badge padding now uses spacing tokens (`var(--space-0h) var(--space-2)`) instead of hardcoded `2px 8px` ## [0.16.3] - 2026-04-13 ### Added - i18n: five new UI languages - French (fr), Turkish (tr), Russian (ru), Greek (el), and Chinese Simplified (zh) with full translations of all keys - Budget: TRY (Turkish Lira) and RUB (Russian Ruble) added to the list of selectable currencies in Settings - i18n: Italian locale now includes the complete `rrule` section (was missing previously) ## [0.16.2] - 2026-04-13 ### Added - Budget: CNY (Chinese Yuan) added to the list of selectable currencies in Settings (#42) ## [0.16.1] - 2026-04-13 ### Fixed - i18n: fallback language for unsupported browser locales changed from German to English (#43) - Apple CalDAV sync: calendar events with a `TZID` parameter are now correctly converted to UTC instead of being treated as floating local time, fixing wrong start times for events synced from iOS Calendar (#43) ## [0.16.0] - 2026-04-06 ### Added - Settings: categorized tab navigation - six tabs (General, Meals, Budget, Shopping, Calendar, Account) replace the flat scrolling layout (#30) - Settings: active tab persists across page navigations via sessionStorage - Settings: Calendar tab is automatically activated when returning from a Google/Apple OAuth callback - Settings: tab bar is sticky so it stays visible while scrolling through tab content - Settings: all tab labels fully translated in de, en, es, it, sv ## [0.15.0] - 2026-04-06 ### Changed - Modal: two-column form layouts now use reusable `.modal-grid` and `.modal-grid--2` CSS classes instead of inline `style` attributes - applied across Calendar, Meals, and Tasks modals (#38) - Modal: panel on mobile now has a subtle border and large shadow for better depth and visual separation (#38) - Modal: form groups inside grid layouts no longer need inline `margin-bottom:0` overrides - handled by `.modal-grid > .form-group` rule (#38) ## [0.14.4] - 2026-04-06 ### Fixed - PWA iOS: pinch-to-zoom disabled - added `user-scalable=no, maximum-scale=1` to viewport meta tag for native-app feel (#16) - PWA iOS: residual body scroll fully blocked - added `overflow: hidden` to `html, body` so any minimal content overflow can no longer make the page body scrollable (#16) - Service worker cache bumped to v28/v27 (#16) ## [0.14.3] - 2026-04-06 ### Fixed - PWA iOS: scroll bleed fully resolved - `padding-top: env(safe-area-inset-top)` moved from `body` to `.app-shell`; body-padding was pushing `.app-shell` (height: 100dvh) beyond the viewport bottom, allowing the page body itself to scroll (#16) - PWA iOS: all fixed-height page containers (Calendar, Shopping, Meals, Notes, Budget, Contacts) now subtract `--safe-area-inset-top` from their height calculation so they no longer overflow `.app-content` in standalone mode (#16) - Added `--safe-area-inset-top` CSS token (mirrors `env(safe-area-inset-top, 0px)`) for consistent use across all page layout calculations (#16) - Service worker cache bumped to v27/v26 to ensure CSS changes are picked up on next update (#16) ## [0.14.2] - 2026-04-06 ### Fixed - Modal: overlay tap now reliably closes the modal on iOS Safari / PWA - added `cursor: pointer` to the overlay (iOS requires this on non-interactive elements to fire click events) and a `touchend` fallback (#29) - Modal: close button enlarged from 32px to 40px to meet Apple's 44px touch-target recommendation (#29) - Modal: swipe-to-close no longer triggers when scrolling content inside the sheet - drag only activates from the top handle zone or when the panel is scrolled to the top (#29) ## [0.14.1] - 2026-04-06 ### Fixed - Calendar: toolbar no longer overflows on narrow screens (< 580px) - view buttons (Monat/Woche/Tag/Agenda) now wrap to a second row so navigation and label remain fully visible (#31) - Tasks: page title no longer visually overlaps action buttons on narrow screens - title now truncates with ellipsis when space is constrained (#31) - Shopping: list name no longer overlaps action buttons when the name is long or the "clear checked" button is visible - name now truncates cleanly (#31) ## [0.14.0] - 2026-04-05 ### Added - Spanish (Español) translation - all sections fully translated (tasks, calendar, meals, shopping, budget, notes, contacts, settings) (#28) ## [0.13.0] - 2026-04-05 ### Added - Meals: optional recipe link per meal - add a URL in the meal modal and a link icon appears on the card for one-tap access to the recipe (#18) - Meals: `recipe_url` field stored in the database (migration v6) ## [0.12.0] - 2026-04-05 ### Added - Shopping: custom categories - add, rename, delete and reorder shopping list categories in Settings → Shopping (#26) - Shopping: categories are now stored in the database (`shopping_categories` table, migration v5) and fully customizable per household - Shopping: category order in the shopping list reflects the custom sort order from Settings - Shopping: items belonging to a deleted category are automatically moved to the next available category ## [0.11.9] - 2026-04-05 ### Changed - README: updated highlights to mention Kanban quick-status buttons and configurable budget currency; replaced docker badge with GHCR link - docs/installation.md: restructured setup into Option A (pre-built GHCR image, no clone needed) and Option B (build from source); updated Updates section accordingly; added tip to SQLCipher troubleshooting entry - docs/index.html (GitHub Pages): updated Get Started code block to show pre-built image path; updated task and budget feature descriptions (EN + DE) to reflect new features ## [0.11.8] - 2026-04-05 ### Changed - `docker-compose.yml` now references the pre-built GHCR image (`ghcr.io/ulsklyc/oikos:latest`) by default - no local build needed to get started (#25) - README Quick Start now shows both the pre-built image path (no clone required) and the build-from-source path ## [0.11.7] - 2026-04-05 ### Added - Kanban view: quick-status button on each card to advance status without drag-and-drop (open → in progress → done → open) - useful for touch devices and kiosk browsers (#24) ## [0.11.6] - 2026-04-05 ### Fixed - Swedish translation: added missing rrule keys (recurrence frequency, weekday abbreviations, unit labels) - contributed by @olsson82 (#23) ## [0.11.5] - 2026-04-05 ### Fixed - Shopping list category dropdown now shows translated labels instead of hardcoded German strings (#21) - Recurrence fields in task and calendar modals now fully translated (labels, frequency options, weekday abbreviations, unit labels) (#21) ## [0.11.3] - 2026-04-05 ### Added - Swedish (Svenska) translation - contributed by @olsson82 (#19) - Italian (Italiano) is now explicitly listed as a language option in Settings ## [0.11.2] - 2026-04-05 ### Added - Configurable currency for the budget section: choose from 13 currencies (EUR, USD, GBP, SEK, NOK, DKK, CHF, PLN, CZK, HUF, JPY, AUD, CAD) in Settings → Budget (#20) - Currency preference is stored household-wide via the preferences API and applied to all budget amounts and formatting ## [0.11.1] - 2026-04-05 ### Fixed - Fix dashboard meal widget ignoring meal type visibility settings - todayMeals query now reads visible_meal_types from sync_config and filters accordingly, consistent with the Meals page (#14) ## [0.11.0] - 2026-04-05 ### Added - Microinteraction improvements: subtle entrance animations, hover/active feedback, and transition polish across cards, buttons, FABs, and nav items ### Fixed - Fix touch scroll on dashboard and all pages - use `height` instead of `min-height` on app-shell to prevent overflow blocking touch scroll on iOS/Android - Add `inputmode` and `autocomplete` attributes to form inputs for better mobile keyboard and autofill UX - Resolve design system audit violations: align spacing, color, border-radius, and shadow usage to tokens throughout all pages and components - Fix touch scrolling regression in calendar, budget, and contacts introduced by layout refactor ## [0.10.0] - 2026-04-04 ### Added - Customizable meal type visibility: toggle breakfast, lunch, dinner, snack on/off in Settings (#14) - New household-wide preferences API (`GET/PUT /api/v1/preferences`) using existing `sync_config` table - New "Meal Plan" section in Settings page with checkbox toggles per meal type - Meals page filters displayed slots based on household preference - i18n keys for meal visibility settings in DE, EN, IT ## [0.9.1] - 2026-04-04 ### Added - Persist task view mode (list/kanban) across sessions via localStorage (#17) - Support URL parameter `?view=kanban` to open tasks directly in Kanban view - ideal for tablet kiosk setups - View toggle button reflects the persisted/URL-driven view on page load ## [0.9.0] - 2026-04-04 ### Added - Optional task priority: new "None" level allows tasks without urgency, reducing visual noise for routine tasks (#15) - "None" is now the default priority for new tasks - Tasks with no priority hide the priority badge entirely in list and dashboard views - DB migration v4 extends priority CHECK constraint to include 'none' - i18n keys for "None" priority in de, en, it locales ## [0.8.2] - 2026-04-04 ### Fixed - Fix UI overlap and scroll bleed on iOS PWA - remove double safe-area padding from body that caused content to shift under status bar (#16) - Fix page containers using wrong nav height token (56px instead of 68px including dot indicator), causing content to render behind bottom nav on all pages - Add `overflow: hidden` to all fixed-height page containers (shopping, meals, notes, budget, contacts) to prevent scroll bleed - Add `overscroll-behavior-y: contain` to app-content to prevent rubber-banding scroll propagation - Fix FAB position on all pages to account for full bottom nav height including dot indicator - Bump service worker cache version to v23 ## [0.8.1] - 2026-04-04 ### Fixed - Replace native `prompt()` dialogs with custom modals in shopping (create/rename list), tasks (add subtask), and meals (choose shopping list) - native prompts were unreliable on mobile/PWA, requiring multiple clicks to close (#12) ## [0.8.0] - 2026-04-04 ### Added - Shopping list widget on dashboard - shows lists with open items, progress bar, and item preview (discussion #9) ## [0.7.7] - 2026-04-04 ### Fixed - Fix modal not closing on mobile when tapping Cancel or Save - add fallback timer for cases where CSS animationend event does not fire (prefers-reduced-motion, tab switch, etc.) ## [0.7.6] - 2026-04-04 ### Fixed - Fix untranslated category names in tasks (group headers), budget (bar chart labels, transaction meta) - all displayed category strings now go through i18n mapping (#11) ## [0.7.5] - 2026-04-04 ### Fixed - Fix flash of unstyled content (FOUC) during page transitions - old module stylesheet is now kept until old content is removed from DOM, new content hidden until render completes - Smooth nav-item tap transition (0.12s ease) instead of abrupt scale snap - Add `:focus-visible` outline to interactive cards, buttons, FABs, and toggles for keyboard navigation ### Added - Custom iOS-style toggle switch component (`.toggle`) replacing native checkboxes in calendar, notes, and budget modals - Toast notification icons - SVG checkmark (success), alert circle (danger), warning triangle (warning) alongside color coding - Empty-state fade-in animation (0.4s ease-out, respects `prefers-reduced-motion`) - Swipe haptic feedback at threshold - `vibrate(15)` fires when swipe reaches 80px during touchmove in tasks and shopping - Interface design system documentation (`.interface-design/system.md`) ## [0.7.4] - 2026-04-04 ### Fixed - Replace hardcoded `box-shadow` values in `.btn--primary` with `--shadow-sm` / `--shadow-md` tokens - Replace `border-radius: 50%` with `var(--radius-full)` in layout and calendar styles - Align ~25 off-grid spacing values (5px, 6px, 7px, 14px, 15px, 22px, 26px, 34px) to 4px grid using `--space-*` tokens ### Changed - Extract 8 hardcoded `rgba()` colors from dashboard, shopping, and weather styles into new design tokens (`--color-glass`, `--color-glass-hover`, `--color-glass-border`, `--color-danger-translucent`) ## [0.7.3] - 2026-04-04 ### Accessibility - Increase font-size to 16px (`--text-md`) on mobile for `quick-add__input`, `quick-add__qty`, `quick-add__cat` (shopping), `notes-toolbar__search-input`, and `contacts-toolbar__search-input` - prevents iOS auto-zoom on input focus (WCAG touch-friendly inputs) ### Performance - Lazy-load page-specific stylesheets on route change instead of loading all 10 upfront in `index.html` - reduces initial CSS payload; only tokens, reset, pwa, layout, and login styles are render-blocking ## [0.7.2] - 2026-04-04 ### Accessibility - Rename `#page-content` to `#main-content` so the existing skip-to-content link targets the semantic `
` landmark correctly - Add `sr-only` priority labels to dashboard task items - screen readers now announce priority level instead of relying on color alone (WCAG 1.4.1) ### Fixed - Replace hardcoded hex values in greeting widget gradient with `--color-accent-active` / `--color-accent` tokens - dark mode now correctly themes the greeting banner - Replace hardcoded `gap: 2px` with `--space-0h` token in greeting widget ## [0.7.1] - 2026-04-04 ### Security - Fix stored XSS across all pages - extract shared `esc()` utility (`public/utils/html.js`) and apply HTML escaping to all user-controlled data in innerHTML templates (titles, names, locations, descriptions, colors, notes content, autocomplete suggestions) - Remove `user-scalable=no` and `maximum-scale=1` from viewport meta tag - restores pinch-to-zoom accessibility (WCAG 1.4.4) ### Changed - Deduplicate 8 identical `escHtml()` functions (tasks, shopping, calendar, notes, meals, contacts, budget, settings) into single shared `esc()` import from `utils/html.js` - Shared `esc()` also escapes single quotes (`'` to `'`) for safer attribute contexts ## [0.7.0] - 2026-04-04 ### Security - Upgrade bcrypt from 5.1.1 to 6.0.0 - resolves 4 HIGH path traversal CVEs in transitive `tar` dependency via `@mapbox/node-pre-gyp` - Remove hardcoded fallback session secret - server now always throws if `SESSION_SECRET` is unset, regardless of `NODE_ENV` ### Changed - **Breaking:** Migrate entire server and test suite from CommonJS to ESM - all `require()`/`module.exports` replaced with `import`/`export`; `"type": "module"` added to `package.json` - Replace 40+ unstructured `console.*` calls with `server/logger.js` - thin wrapper supporting `LOG_LEVEL` env var (debug/info/warn/error), zero new dependencies - Translate `package.json` description to English for consistency with all other documentation - Translate `.env.example` comments from German to English for international contributors - Translate `.gitignore` comments to English ### Removed - Remove internal audit documents (`docs/claude-md-audit.md`, `docs/repo-audit-2026-04-02.md`) from tracked files - Remove empty `.worktrees/` leftover directory ### Added - Add `CODE_OF_CONDUCT.md` (Contributor Covenant v2.1) - Add `.gitignore` patterns for audit report files (`docs/audit-report-*.md`, `docs/*-audit.md`) ## [0.6.0] - 2026-04-03 ### Fixed - Fix budget entry update failing with "Internal Error" when changing category - `date` validator import shadowed the `date` field from the request body, causing SQLite to receive a function reference instead of a string value (fixes #8) ## [0.5.9] - 2026-04-03 ### Security - Fix stored XSS in task titles and subtask titles - all user-provided text in tasks.js is now escaped via `escHtml()` before insertion into innerHTML templates - Fix stored XSS in settings page member list - display_name and username are now escaped via `escHtml()` in `memberHtml()` - Fix rate limiter bypass via X-Forwarded-For IP spoofing - `trust proxy` now defaults to `loopback` instead of unconditional `1`; configurable via `TRUST_PROXY` env var - Fix Google OAuth CSRF - add cryptographic `state` parameter to OAuth flow, validated on callback - Fix CSV injection in budget export - fields starting with `=`, `+`, `-`, `@`, tab, or carriage return are now prefixed with apostrophe - Fix missing session invalidation on user deletion - all active sessions of deleted users are now destroyed - Restrict username to `[a-zA-Z0-9._-]` with minimum 3 characters, preventing HTML/script injection via usernames - Restrict Google Calendar sync trigger (`POST /google/sync`) and Apple Calendar sync trigger (`POST /apple/sync`) to admin role - Add warning log when Apple CalDAV credentials are stored without DB encryption enabled ## [0.5.8] - 2026-04-03 ### Added - Add Italian (Italiano) localization - full translation of all 497 i18n keys (thanks @albanobattistella, PR #7) - Add Italian as selectable language in Settings locale picker ## [0.5.7] - 2026-04-03 ### Fixed - Fix recurring calendar events not expanding - RRULE parser now strips the `RRULE:` prefix used by ICS/CalDAV, which previously caused all recurrence rules to be silently ignored - Fix recurring multi-day events not appearing when their start date falls before the view window but the event spans into it - Fix all-day recurring event instances getting datetime end values instead of date-only format - Add YEARLY recurrence frequency support for birthday and anniversary events ## [0.5.6] - 2026-04-03 ### Fixed - Fix all-day calendar events appearing on the correct day and the following day - ICS DTEND for DATE values is exclusive per RFC 5545, now correctly adjusted (fixes #5) - Fix multi-day events not showing when using DURATION instead of DTEND - add ICS DURATION property support in CalDAV parser - Fix birthdays from Apple Calendar not syncing - birthday calendars are no longer excluded from sync - Fix outbound ICS builder using inclusive DTEND for all-day events - now correctly emits exclusive DTEND per RFC 5545 ## [0.5.5] - 2026-04-03 ### Fixed - Fix iCloud Calendar sync failing with FOREIGN KEY constraint error - `created_by` was hardcoded to user ID 1 instead of resolving dynamically (fixes #4) - Sync all iCloud calendars instead of only the first one - previously only a single calendar was imported, ignoring Family, subscribed, and other calendars - Add missing `cfgDel` helper function used by `clearCredentials` - disconnecting Apple Calendar would crash - Skip unreachable or broken calendars gracefully instead of aborting the entire sync ## [0.5.4] - 2026-04-03 ### Fixed - Fix SQLCipher PRAGMA key syntax error on fresh install - hex-encoded key must be wrapped in double quotes for valid PRAGMA syntax (fixes #3) ## [0.5.3] - 2026-04-03 ### Security - Fix SQLCipher PRAGMA key interpolation - encryption keys containing single quotes no longer crash on startup; key is now hex-encoded - Enforce minimum password length (8 characters) when admin creates new users - previously any 1-character password was accepted - Add length bounds on username (64 chars) and display_name (128 chars) to prevent unbounded input - Add input length bounds on login (username 64 chars, password 1024 chars) - Invalidate all other sessions when a user changes their password - previously active sessions survived password reset - Session and CSRF cookies now have `secure: true` by default; HTTP is only allowed when `SESSION_SECURE=false` is explicitly set in `.env` - previously cookies were sent without `Secure` flag in non-production environments - Document authorization model in SECURITY.md - clarify that all family members share read/write access to all data by design ### Changed - Use multi-stage Docker build to exclude build tools (python3, make, g++) from runtime image - Exclude `docs/` directory from Docker image via `.dockerignore` - Consolidate `dotenv.config()` to single call in `server/index.js` - remove duplicate calls from `server/db.js` and `server/auth.js` ## [0.5.2] - 2026-04-01 ### Security - Add rate limiting to SPA fallback route to prevent file system hammering via unauthenticated wildcard requests - Add CSRF protection to auth routes that change state (logout, create user, change password, delete user) - previously bypassed global CSRF middleware due to router registration order - Fix incomplete vCard escaping in contacts export - backslash characters are now escaped first before other special characters (`,`, `;`, newline), preventing injection via contact fields - Restrict CI workflow GITHUB_TOKEN to `contents: read` (principle of least privilege) ## [0.5.1] - 2026-04-01 ### Fixed - Meals: fixed crash when dragging a meal slot - `dragging` state is now destructured before `cleanup()` runs, preventing a null-reference error on drop - i18n: `t()` now resolves dot-notation keys against nested locale JSON objects (e.g. `t('nav.tasks')` correctly returns `"Aufgaben"` instead of the raw key string); affects all pages, components, and navigation - PWA: replaced placeholder "O" icons with the actual Oikos house logo across all icon variants (192, 512, maskable 192, maskable 512, apple-touch-icon, favicon); maskable variants use full-bleed background with logo within the 80% safe zone - fixes Android home screen showing only a blue circle - PWA: weather widget icons (OpenWeatherMap) now render correctly in installed PWA on Android; service worker no longer intercepts cross-origin image requests (opaque responses caused silent rendering failures in standalone mode) - Settings: language selector replaced from cramped radio buttons to a native `