Files
oikos/CHANGELOG.md
T
Ulas 35186ca87f fix: change SameSite=Strict to SameSite=Lax for session and CSRF cookies (#46)
Safari's ITP blocks Strict cookies on certain navigations (direct URL entry,
reverse proxy context), resulting in a 401 on login even with valid credentials.
Lax is safe: CSRF attacks are prevented by the double-submit token and the
HTTPS-only secure flag. Firefox and Chrome were unaffected.
2026-04-13 21:36:35 +02:00

38 KiB
Raw Blame History

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

[0.17.2] - 2026-04-13

Fixed

  • Auth: session cookie and CSRF cookie changed from SameSite=Strict to SameSite=Lax - Safari's ITP (Intelligent Tracking Prevention) was blocking Strict cookies on certain navigations (direct URL entry, reverse proxy), causing a 401 on login while other browsers worked fine (#46)

[0.17.1] - 2026-04-13

Fixed

  • Service worker: glass.css was missing from the shell cache list - on already-installed PWA instances the file was never loaded and no glass effects were visible; cache bumped to shell-v29
  • CSS load order: .widget glass shadow and border were overridden by dashboard.css (module CSS loads after glass.css); glass styles moved directly into dashboard.css
  • CSS load order: .filter-chip--active glass state was overridden by tasks.css; @supports backdrop-filter block moved into tasks.css
  • CSS load order: .priority-badge border-radius was reset to var(--radius-xs) by tasks.css, losing the capsule shape; corrected to var(--radius-glass-chip) in tasks.css
  • glass.css: removed dead .sticky-header rule (class is not used anywhere in the HTML)

[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 <main> 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 &#39;) 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 <select> dropdown using the standard form-input style

Changed

  • PWA manifest: added id field and display_override array for reliable Chrome Android PWA recognition; manifest.json is now served with Content-Type: application/manifest+json
  • Service worker (v22): /i18n.js and locale files added to app-shell cache; cross-origin asset requests excluded from cache-first strategy

0.5.0 - 2026-03-31

Added

  • i18n: full internationalisation system (public/i18n.js) with German (de) and English (en) support; language auto-detected from navigator.language, overridable via Settings
  • i18n: all user-facing strings moved to locale files (public/locales/de.json, public/locales/en.json); 489 translation keys covering all modules
  • i18n: locale switch without page reload - all pages, components and navigation re-render via locale-changed custom event
  • i18n: oikos-locale-picker Web Component in Settings - three options: System (follows browser language), Deutsch, English
  • i18n: dates and times formatted with Intl.DateTimeFormat using the active locale; formatDate() and formatTime() exported from i18n.js
  • i18n: fallback chain (active locale → German → key) ensures no untranslated keys are shown even if a future locale file is incomplete
  • i18n: adding a new language requires only one JSON file (public/locales/xx.json) and one line in SUPPORTED_LOCALES

0.4.0 - 2026-03-31

Fixed

  • Mobile: toast notifications no longer overlap with the bottom navigation bar - introduced --nav-bottom-height token (scroll area 56px + dots indicator 12px) used consistently by toast container and app content padding
  • Mobile: FAB and page-FAB are now hidden when the virtual keyboard is open, preventing them from covering form inputs; detection uses visualViewport.resize with a 75% height threshold
  • UI: added missing dark-mode colour overrides for shopping, notes, contacts, budget, and settings module tokens - accent stripes now render at readable pastel values in dark theme
  • UI: meals week-navigation bar now shows module accent top-border stripe; settings page now declares --module-accent for consistency with all other modules

Added

  • Shopping: swipe-left to toggle checked/unchecked, swipe-right to delete items on mobile; × delete button hidden on mobile in favour of swipe gesture
  • Notes: client-side full-text search bar in toolbar - filters by title and content instantly; shows "Keine Treffer" empty state when no match
  • Dashboard: weather widget refresh button (top-right corner) + automatic 30-minute refresh interval; interval is cleared when navigating away
  • Contacts: vCard export button per contact (downloads .vcf file); vCard import via file input in toolbar (parses FN, TEL, EMAIL, ADR, NOTE, CATEGORIES fields)
  • PWA: offline fallback page (/offline.html) served by service worker when network is unavailable and index.html is not cached; page includes a reload button
  • UI: module accent colours now applied to three visual layers - active nav tab (bottom bar + sidebar), toolbar top-border stripe, and list/card left-border stripe - giving each module a distinct colour identity

0.3.0 - 2026-03-31

Added

  • Calendar: recurring events are now expanded in GET /api/v1/calendar - all occurrences within the requested date window are returned as virtual instances; duration is preserved; instances are marked with is_recurring_instance=1 and shown with a ↻ icon in the agenda view; /upcoming also expands recurring events within a 90-day window
  • Budget: recurring entries auto-generate instances for each viewed month; instances deleted by the user are skipped permanently via budget_recurrence_skipped table; generated instances are marked with ↩ in the transaction list
  • Budget: month-over-month comparison in summary cards - each card (Einnahmen, Ausgaben, Saldo) shows a trend line (▲/▼ + delta amount vs. previous month); previous month summary is fetched in parallel with current month
  • Meals: drag & drop between slots and days using Pointer Events (touch + mouse); ghost element follows pointer; drop on occupied slot swaps meals; reduced-motion: no ghost animation, interaction still works
  • Settings: Apple CalDAV credentials form (URL, Apple-ID, app-specific password) with live connection test; admin can connect and disconnect via UI without restarting the server; DB-stored credentials take precedence over .env vars; auto-sync runs every 15 min (configurable via SYNC_INTERVAL_MINUTES)

0.2.1 - 2026-03-30

Fixed

  • Accumulating click listeners on #notes-grid: listener is now registered once in render() via event delegation instead of re-registered in every renderGrid() call
  • Accumulating anonymous document click listener in dashboard FAB: initFab() now accepts an AbortSignal; render() aborts the previous signal before creating a new one, eliminating listener leaks across navigation cycles
  • Add btnError() shake feedback to notes.js save error handler for consistency with other modules
  • Calendar event popup closePopup listener now checks popup.isConnected to self-remove correctly after navigation without a click

Added

  • CSS alias .form-label alongside .label to cover usage in notes.js and settings.js without requiring a mass-rename
  • Tests for wireBlurValidation, btnSuccess, and btnError (12 cases) in test-modal-utils.js

0.2.0 - 2026-03-30

Changed

  • Directional slide-x page transitions (forward = right, backward = left) with race condition guard
  • PWA install prompt delayed until 2 user interactions; dismiss window reduced from 30 to 7 days; interaction counter resets on dismiss
  • Unified card padding to 16px (--space-4) across tasks, contacts, budget, and meals modules

Added

  • Staggered fade-in animation for list items on page load across all modules (tasks, shopping, meals, contacts, budget, notes, calendar agenda)
  • Unified empty states using shared .empty-state class across all modules (replaces per-module CSS)
  • stagger() and vibrate() UX utilities in public/utils/ux.js with full test coverage
  • Proportional opacity on swipe-reveal action areas in tasks (already implemented, confirmed)
  • FAB colors tied to per-module accent tokens via CSS custom properties
  • scrollIntoView for focused inputs when virtual keyboard opens in modals (300ms delay)
  • Consistent vibration feedback via vibrate() utility across tasks, shopping, contacts, budget, and notes
  • Bottom sheet modal on mobile (< 768px) with drag handle, slide-in animation, and swipe-to-close
  • Enter-key navigation between form fields in modals; Enter on last field triggers submit
  • Blur-triggered inline validation for required fields with error/success border states
  • wireBlurValidation(), btnSuccess(), and btnError() exported from modal.js
  • Submit button checkmark-success (700ms) and shake-error feedback animations

0.1.0 - 2026-03-29

Initial release of Oikos - a self-hosted family planner for 26 person households. Runs as a Docker container behind Nginx with SSL, no cloud dependency.

Added

  • Dashboard with time-of-day greeting, urgent tasks, upcoming events, today's meals, pinned notes, and weather widget (OpenWeatherMap integration with 35 day forecast scaling by screen size)
  • Task management with categories, priorities, due dates, subtasks (max 2 levels), list and Kanban views, swipe gestures on mobile (swipe left = toggle done, swipe right = edit), and recurring tasks via iCal RRULE
  • Shopping lists with multiple named lists, supermarket-aisle sorting, autocomplete from history, optimistic checkbox toggle, and bulk-clear of checked items
  • Weekly meal planner with breakfast/lunch/dinner/snack grid (MonSun), ingredient tracking per meal, and one-click transfer of ingredients to shopping lists
  • Calendar with month, week, day, and agenda views, multi-day event support, color-coded entries, and family member assignment
  • Google Calendar sync via OAuth 2.0 with incremental sync tokens and Apple CalDAV sync via tsdav, both bidirectional
  • Pinboard (notes) with color-coded sticky notes, pin-to-top, Markdown formatting toolbar (bold, italic, lists, headings, code, links), and automatic text contrast based on background color
  • Contacts directory with category filtering (doctor, emergency, trades, etc.), full-text search, and direct tel:/mailto:/maps: links
  • Budget tracker with income/expense logging, monthly navigation, category breakdown bar charts (pure CSS), and CSV export
  • Settings page for password change, calendar sync status, and family member management
  • Authentication with session-based login (bcrypt, httpOnly/secure/sameSite cookies, 7-day TTL), admin-only user creation, and rate-limited login (5 attempts/min with 15-min lockout)
  • CSRF protection using Double Submit Cookie pattern with timing-safe comparison
  • Progressive Web App with app-shell caching (service worker with stale-while-revalidate for static assets, network-first for navigation, network-only for API), custom install prompt for Android and iOS, dynamic theme-color per module, safe area inset handling, and offline fallback
  • Responsive design with mobile bottom navigation (swipeable pages with dot indicator), collapsible sidebar on tablet, and full sidebar on desktop
  • Dark mode with system preference detection and manual toggle, warm-tinted neutral color scale
  • Design system with CSS custom properties (tokens for colors, spacing, typography, shadows, radii, z-indices), module-specific accent colors, and consistent component patterns
  • Accessibility improvements: skip link, sr-only headings on all pages, aria-hidden decorative icons, aria-label on icon-only buttons, token-based touch targets (4448px), 12px minimum font size, and prefers-reduced-motion support
  • Docker deployment with docker-compose, optional SQLCipher encryption (AES-256), and nginx.conf example
  • Setup script (node setup.js) for initial admin account creation with LAN-reachable URL display
  • Input validation middleware with centralized rules (string length, date/time format, enum, color) across all API routes
  • Content Security Policy via Helmet with strict CSP, self-hosted Lucide Icons (no CDN at runtime)
  • Lazy loading with per-page ES module imports cached in memory, Cache-Control headers (immutable for assets, must-revalidate for code), and service worker update notification

Security

  • Fail-fast on missing SESSION_SECRET in production
  • Rate limiting on login endpoint and global API limiter (300 req/min/IP)
  • No user data cached by service worker (API requests are network-only)
  • Hardened .gitignore and .dockerignore to prevent accidental secret or binary leakage