# 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.25.2] - 2026-04-26 ### Changed - Docs: `SPEC.md` updated to reflect all changes since v0.24.0 — Budget Entries table now documents `subcategory` column and DB-backed `category` FK; new `Budget Categories`, `Budget Subcategories`, and `API Tokens` data-model tables added; Settings section updated with API Tokens tab, corrected language list (added Japanese, Arabic, Hindi, Portuguese), and tab count (six → seven); Budget module section now covers subcategories, custom categories, and all new endpoints; new API Documentation section documents OpenAPI 3.0 spec and authentication options; design tokens `--blur-2xs` and `--module-reminders` added to Colors section - Docs: `README.md` Highlights updated — Budget Tracking now mentions DB-backed subcategories; new API Tokens entry added ## [0.25.1] - 2026-04-26 ### Changed - Dashboard: empty widget states now render as a compact inline row (icon + text) instead of a centred column, saving ~40px of vertical space per empty widget on mobile ### Fixed - Dashboard: widget body bottom padding increased from 12px to 16px for slightly more breathing room - Dashboard: widget reordering in "Anpassen" modal now uses the View Transition API for smooth animations; respects `prefers-reduced-motion` ## [0.25.0] - 2026-04-25 ### Added - API token authentication: admins can create named Bearer / X-API-Key tokens for external integrations; tokens are SHA-256-hashed at rest, support optional expiry and revocation, and track last-used timestamp - Settings: new "API Tokens" section for admins to create and revoke tokens; the full token value is shown only once immediately after creation - OpenAPI 3.0 specification served at `/api/v1/openapi.json` and `/openapi.json` (download via `?download=1`) - Budget: new endpoints `GET /api/v1/budget/categories` and `GET /api/v1/budget/categories/:key/subcategories` with optional `?lang=` localisation ### Changed - `server/logger.js` now serialises `Error` objects into structured JSON fields (name, message, stack) instead of logging `{}` ## [0.24.4] - 2026-04-26 ### Added - Accessibility: `layout.css` now has a `@media (prefers-contrast: more)` block — ghost and secondary buttons get explicit borders, cards lose decorative shadows, form inputs get a 2px border, focus rings become thicker (3px, 4px offset), and active nav items get an underline as a colour-independent indicator ### Fixed - Design tokens: corrected `--sidebar-width-expanded` comment from `1280px+` to `1440px+` to match the actual breakpoint in `layout.css` ## [0.24.3] - 2026-04-26 ### Added - Design tokens: `--blur-2xs: blur(2px)` added to the blur scale — fills the gap below `--blur-xs` (4px), used for subtle overlay blurs - Design tokens: `--module-reminders: #0E7490` (Cyan-700, WCAG AA) added for the reminders feature; dark mode variant `#22D3EE` (Cyan-400) ### Fixed - Design tokens: hardcoded `blur(16px)`, `blur(2px)`, and `blur(12px)` in `layout.css` replaced with `var(--blur-md)`, `var(--blur-2xs)`, and `var(--blur-sm)` — `prefers-reduced-transparency` now correctly disables all backdrop-filter effects including bottom nav, more-sheet backdrop, and sticky headers - Accessibility: `layout.css` now has a `prefers-reduced-transparency` block for `.nav-bottom`, `.more-backdrop`, and `.sticky-header` — these three elements previously kept their backdrop-filter active even when the user requested reduced transparency - Reminders: reminder bell icon in toasts now uses `var(--module-reminders)` instead of the generic `var(--color-accent)` ## [0.24.2] - 2026-04-26 ### Fixed - Design tokens: added missing `--shadow-xl` and `--shadow-xs` tokens (with dark mode variants) — resolves undefined CSS custom property references in kanban drag ghost and dashboard widget toggle - Design tokens: `--color-surface-raised` replaced with `--color-surface-hover` in `dashboard.css` — was undefined, causing unstyled hover states in the widget customizer - Design tokens: `--color-text` replaced with `--color-text-primary` in `dashboard.css` — was undefined, causing invisible text on hover in the widget customizer - Design tokens: hardcoded `font-weight` values (`700`, `500`, `600`) in `reminders.css` replaced with `--font-weight-bold`, `--font-weight-medium`, `--font-weight-semibold` ## [0.24.1] - 2026-04-25 ### Fixed - Accessibility: skip-to-content link added to `index.html` — keyboard users can now bypass navigation and jump directly to main content - Accessibility: removed `role="presentation"` from modal overlay — restores screen reader access and resolves conflict with existing `aria-label` - Accessibility: search overlay now traps keyboard focus — tabbing can no longer escape the overlay into the hidden page behind it - Interaction: modal swipe-to-close — kept `dragging` flag active on upswing so the panel snaps back correctly instead of getting stuck - Rendering: SVG gradient IDs in the logo are now unique per render — prevents DOM ID collisions when the logo is mounted more than once - Touch targets: `.btn--icon-sm` minimum size raised from 36×36px to 44×44px (`--target-base`) — meets iOS minimum touch target guideline - Design tokens: added `--target-base: 44px` and documented `--target-sm: 32px` as visual-only (not a touch target) ## [0.24.0] - 2026-04-25 ### Added - Budget: expense categories are now stored in the database (`budget_categories` table) as stable English slugs, replacing hardcoded German strings - Budget: subcategory support for all expense entries — 35 predefined subcategories across 8 top-level categories (housing, food, transport, personal_health, leisure, shopping_clothing, education, financial_other) - Budget: users can add custom categories and subcategories directly from the entry modal via inline "+ category" / "+ subcategory" buttons - Budget: new API endpoints `POST /api/v1/budget/categories` and `POST /api/v1/budget/categories/:key/subcategories` for custom category/subcategory creation - Budget: subcategory displayed alongside category in each entry's metadata line - Budget: CSV export now includes a subcategory column and English column headers - i18n: all 14 non-German locales extended with new budget category keys (`catHousing`, `catTransport`, `catPersonalHealth`, `catShoppingClothing`, `catFinancialOther`) and all 35 subcategory label keys - All server-side log messages and API error strings translated from German to English — contributed by @rafaelfoster ### Changed - Budget category labels for existing entries migrated to new slug keys via DB migration 15; display names remain fully localised through the i18n system ## [0.23.17] - 2026-04-25 ### Fixed - Italian (it) locale: translated all missing strings in the recipes section (`nav.recipes`, `meals.savedRecipeLabel`, `meals.savedRecipePlaceholder`, `meals.saveAsRecipe`, `meals.recipeScaleLabel`, and all `recipes.*` keys) — contributed by @albanobattistella ## [0.23.16] - 2026-04-24 ### Changed - Design tokens: replaced all remaining hardcoded color and size values in `layout.css`, `glass.css`, `dashboard.css`, and `reminders.css` with CSS custom properties - Design tokens: added `--text-2xs`, `--color-overlay-glass`, `--color-backdrop-glass`, `--glass-border-overlay`, `--glass-highlight-mid`, `--glass-inset-bottom-base`, `--glass-inset-bottom-hover`, `--glass-inset-thumb`, and `--glass-inset-input` to `tokens.css` ## [0.23.15] - 2026-04-24 ### Fixed - All non-German locales (ar, el, en, es, fr, hi, it, ja, pt, ru, sv, tr, uk, zh): added missing translation keys for `nav.more`, `calendar.ics.reset/resetToast`, `settings.ics.*`, `tasks.filter*`, `tasks.swiped*`, `search.*`, and `reminders.*` — these were falling back to German strings for all non-German users ## [0.23.14] - 2026-04-23 ### Fixed - Swedish (sv) locale: corrected five translation errors in the recipes section (`titleRequired`, `copySuffix`, `urlLabel`, `openLink`, `emptyDescription`) — contributed by @olsson82 ## [0.23.13] - 2026-04-22 ### Security - Installer: replaced template-literal URL construction with the `URL` constructor when setting the final "Open Oikos" link, eliminating a potential DOM-based XSS vector (CodeQL js/xss-through-dom, GitHub Advisory #7) ## [0.23.12] - 2026-04-22 ### Fixed - iOS PWA: bottom navigation bar gap resolved by removing `overflow: hidden` from `` (iOS Safari bug: this property clips `position: fixed` descendants) and restoring the `body::after` fill approach; nav bar height is no longer inflated by the safe area padding ## [0.23.11] - 2026-04-22 ### Fixed - iOS PWA: bottom navigation bar now extends into the home indicator safe area via `padding-bottom: env(safe-area-inset-bottom)`, reliably eliminating the gap at the screen bottom ## [0.23.10] - 2026-04-22 ### Fixed - iOS PWA: safe area fill now uses the same surface color as the bottom navigation bar, so it matches in both light and dark mode ## [0.23.9] - 2026-04-22 ### Fixed - iOS PWA: a `body::after` pseudo-element now fills the home indicator safe area with the same glass background as the bottom navigation, eliminating the gap between the nav bar and the screen edge ## [0.23.8] - 2026-04-22 ### Fixed - iOS PWA: bottom navigation bar now extends into the home indicator safe area, removing the gap between the nav and the screen edge ## [0.23.7] - 2026-04-22 ### Fixed - Navigation: sidebar logo now uses the official `docs/logo.svg` artwork (house + chimney on gradient background) instead of a generic Lucide home icon; gradient colors are driven by CSS tokens ## [0.23.6] - 2026-04-22 ### Changed - Dashboard: greeting widget now adapts its gradient to the time of day — warm amber-orange in the morning (before 11:00), indigo during the day, and violet in the evening (after 18:00) - Dashboard: FAB speed-dial open/close rotation now uses a spring cubic-bezier for a more natural feel - Navigation: sidebar logo is now a proper SVG house icon on a gradient background instead of the CSS letter placeholder ## [0.23.5] - 2026-04-22 ### Changed - Dashboard: each widget now uses its module accent color (green for tasks, violet for calendar, orange for meals, pink for shopping, amber for notes) for its header icon, badge, and link instead of the global indigo accent - Dashboard: meal slots now display their type-specific color (amber for breakfast, green for lunch, indigo for dinner, orange for snack) on icon and label when a meal is planned - Dashboard: pinned note cards now show a subtle background tint matching the note's color - Dashboard: widget and card hover lift increased from 1 px to 2 px for more perceptible feedback on desktop - Navigation: active bottom-nav tab now shows a pill-shaped highlight behind the icon for a clearer location indicator - Shopping widget: progress bar height increased from 4 px to 6 px for better visual weight - Empty state icons inside widgets now use the tertiary text color instead of the disabled color for improved visibility ## [0.23.4] - 2026-04-22 ### Changed - Docs: web installer (`node tools/installer/install-server.js`) is now Option A in all installation guides (`README.md`, `docs/installation.md`, GitHub Pages `docs/install.html`); the pre-built Docker image method is relabelled Option B and the build-from-source method Option C ## [0.23.3] - 2026-04-22 ### Fixed - Weather widget: wind speed is no longer multiplied by 3.6 when `OPENWEATHER_UNITS=imperial` (the API already returns mph; the conversion was only correct for metric/standard) - Weather widget: wind unit label now shows `mph` for imperial and `km/h` for metric/standard instead of always showing `km/h` ## [0.23.2] - 2026-04-22 ### Fixed - Calendar: ICS-synced events now render at the correct local hour and day in week/day/month/agenda views; day-matching and hour-positioning previously used raw string slices which returned UTC values instead of browser-local time for events stored with a `Z` suffix ## [0.23.1] - 2026-04-22 ### Security - Installer: host and port inputs are now validated against a strict hostname regex and integer range check (1–65535) before being used in any DOM sink or URL template — prevents XSS-through-DOM (CodeQL js/xss-through-dom alert #7) ## [0.23.0] - 2026-04-21 ### Added - Calendar: `external_calendars` DB table (migration v14) stores display name and color per synced Google/Apple calendar; `calendar_events` gains a `calendar_ref_id` FK used for join-based name/color lookup in all calendar and dashboard queries - Calendar: Google and Apple sync services now fetch the calendar's display name and background color via `upsertExternalCalendar()` and persist them to the new table - Calendar: event popup, agenda, month, week, and day views now show the external calendar name as a colored `event-cal-label` badge when `cal_name` is present - Calendar: event popup and dashboard events list now display the event location using `fmtLocation()` which strips RFC 5545 backslash-escapes (`\n`, `\,`, `\;`, `\\`) and normalizes semicolons/newlines to comma-separated inline text - Utils: `fmtLocation(raw)` helper added to `html.js` for normalizing ICS `LOCATION` property strings - i18n: task due-date keys (`tasks.overdue`, `tasks.dueSoon`, `tasks.dueToday`, `tasks.dueTomorrow`, `tasks.noDueDate`) added to all 16 supported locale files ### Changed - Dashboard: widget headers flattened — glass card replaced with transparent surface + bottom border; clock icon added to the urgent-tasks chip; overdue and due-soon counts computed separately using `effectiveDue()` for accuracy - Glass toolbar (desktop ≥ 1024 px): rounded card style (`border-radius`, full `border`) replaced with flat background + `border-top: 3px solid var(--module-accent)` + bottom border only, consistent with other page toolbars - Shopping and Budget page headers: `border-top: 3px solid var(--module-accent)` accent stripe added to `.list-tabs-bar` and `.budget-nav`, matching the visual language of all other module headers - Calendar agenda: event color indicator changed from a 10 px circle to a 3 px full-height left bar (`width: 3px; align-items: stretch`), matching the dashboard upcoming-events style - Tasks: filter panel now defaults to `status: 'open'` on first load instead of showing all tasks including completed ones - SW cache: bumped to `oikos-shell-v50` / `oikos-pages-v45` / `oikos-assets-v45` ### Fixed - Tasks / Dashboard: sort order now strictly follows effective due date ascending; overdue tasks (due date+time in the past) always surface first in all views — list groups, Kanban columns, and the dashboard urgentTasks widget. Priority is used only as a tiebreaker for tasks sharing the same due datetime. Server-side sort moved from SQL to JavaScript using `effectiveDue()` for timezone-correct `due_time` handling (SQLite `DATE('now')` is UTC-only) - Tasks: due date chip now shows the time component when `due_time` is set; overdue/soon/today/tomorrow states are computed against the current moment rather than midnight - Dashboard: widget navigation links changed from `` to `