From cb09c5d0dbe6d8124888c7d127a8400c71cc2ae5 Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Sun, 26 Apr 2026 08:25:26 +0200 Subject: [PATCH 1/8] chore: release v0.24.2 --- CHANGELOG.md | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- public/styles/dashboard.css | 6 +++--- public/styles/reminders.css | 6 +++--- public/styles/tokens.css | 8 ++++++++ 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 035b5d2..193364f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [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 diff --git a/package-lock.json b/package-lock.json index eea26e8..885de36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.24.1", + "version": "0.24.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.24.1", + "version": "0.24.2", "license": "MIT", "dependencies": { "bcrypt": "^6.0.0", diff --git a/package.json b/package.json index ae257c6..d93a3a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.24.1", + "version": "0.24.2", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module", diff --git a/public/styles/dashboard.css b/public/styles/dashboard.css index 9f4977e..b943cb1 100644 --- a/public/styles/dashboard.css +++ b/public/styles/dashboard.css @@ -1125,7 +1125,7 @@ } .customize-row:hover { - background-color: var(--color-surface-raised); + background-color: var(--color-surface-hover); } .customize-row__toggle { @@ -1212,8 +1212,8 @@ } .customize-row__btn:hover:not(:disabled) { - background-color: var(--color-surface-raised); - color: var(--color-text); + background-color: var(--color-surface-hover); + color: var(--color-text-primary); } .customize-row__btn:disabled { diff --git a/public/styles/reminders.css b/public/styles/reminders.css index 6038df7..a7f6cf2 100644 --- a/public/styles/reminders.css +++ b/public/styles/reminders.css @@ -19,7 +19,7 @@ background: var(--color-priority-urgent); color: var(--color-text-on-accent); font-size: var(--text-2xs); - font-weight: 700; + font-weight: var(--font-weight-bold); line-height: 16px; text-align: center; pointer-events: none; @@ -57,7 +57,7 @@ .toast__reminder-text span { font-size: var(--text-sm, 0.875rem); - font-weight: 500; + font-weight: var(--font-weight-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -79,7 +79,7 @@ .reminder-section__title { font-size: var(--text-sm, 0.875rem); - font-weight: 600; + font-weight: var(--font-weight-semibold); color: var(--color-text-primary); } diff --git a/public/styles/tokens.css b/public/styles/tokens.css index e49104c..fbcd122 100644 --- a/public/styles/tokens.css +++ b/public/styles/tokens.css @@ -244,6 +244,10 @@ --shadow-md: var(--_shadow-md); --_shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.04); --shadow-lg: var(--_shadow-lg); + --_shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.18), 0 4px 12px rgba(0, 0, 0, 0.06); + --shadow-xl: var(--_shadow-xl); + --_shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.08); + --shadow-xs: var(--_shadow-xs); /* -------------------------------------------------------- * 9. Border-Radien @@ -542,6 +546,8 @@ --_shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25); --_shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35); --_shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45); + --_shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.60), 0 4px 12px rgba(0, 0, 0, 0.25); + --_shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30); --_glass-bg: rgba(28, 28, 26, 0.75); --_glass-bg-hover: rgba(38, 38, 36, 0.82); @@ -647,6 +653,8 @@ --_shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25); --_shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35); --_shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45); + --_shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.60), 0 4px 12px rgba(0, 0, 0, 0.25); + --_shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30); /* Glass */ --_glass-bg: rgba(28, 28, 26, 0.75); From 5d95ad8d2ae2807aaa867b45a94f8cae923a7cdd Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Sun, 26 Apr 2026 08:42:04 +0200 Subject: [PATCH 2/8] chore: release v0.24.3 --- CHANGELOG.md | 11 +++++++++++ package-lock.json | 4 ++-- package.json | 2 +- public/styles/layout.css | 37 +++++++++++++++++++++++++++++++------ public/styles/reminders.css | 2 +- public/styles/tokens.css | 19 +++++++++++++------ 6 files changed, 59 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 193364f..c04ca29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [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 diff --git a/package-lock.json b/package-lock.json index 885de36..97f781d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.24.2", + "version": "0.24.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.24.2", + "version": "0.24.3", "license": "MIT", "dependencies": { "bcrypt": "^6.0.0", diff --git a/package.json b/package.json index d93a3a6..047b9ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.24.2", + "version": "0.24.3", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module", diff --git a/public/styles/layout.css b/public/styles/layout.css index 4337808..33949d7 100755 --- a/public/styles/layout.css +++ b/public/styles/layout.css @@ -142,8 +142,8 @@ display: flex; flex-direction: column; z-index: var(--z-nav); - backdrop-filter: blur(16px) saturate(180%); - -webkit-backdrop-filter: blur(16px) saturate(180%); + backdrop-filter: var(--blur-md) saturate(180%); + -webkit-backdrop-filter: var(--blur-md) saturate(180%); } /* ── Items-Reihe ── */ @@ -171,8 +171,8 @@ inset: 0; background-color: var(--color-overlay); z-index: calc(var(--z-nav) + 1); - backdrop-filter: blur(2px); - -webkit-backdrop-filter: blur(2px); + backdrop-filter: var(--blur-2xs); + -webkit-backdrop-filter: var(--blur-2xs); } .more-backdrop--visible { @@ -1583,8 +1583,8 @@ top: 0; z-index: var(--z-sticky); background-color: color-mix(in srgb, var(--color-bg) 90%, transparent); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); + backdrop-filter: var(--blur-sm); + -webkit-backdrop-filter: var(--blur-sm); padding-bottom: var(--space-3); margin-bottom: var(--space-4); } @@ -1906,6 +1906,31 @@ border-radius: 0 var(--radius-md) var(--radius-md) 0; } +/* -------------------------------------------------------- + * Reduced Transparency — layout.css Fallbacks + * glass.css deckt Glass-Komponenten ab; diese drei Elemente + * nutzen backdrop-filter außerhalb von @supports und brauchen + * eigene Fallbacks. + * -------------------------------------------------------- */ +@media (prefers-reduced-transparency: reduce) { + .nav-bottom { + background-color: var(--color-surface); + backdrop-filter: none; + -webkit-backdrop-filter: none; + } + + .more-backdrop { + backdrop-filter: none; + -webkit-backdrop-filter: none; + } + + .sticky-header { + background-color: var(--color-bg); + backdrop-filter: none; + -webkit-backdrop-filter: none; + } +} + /* -------------------------------------------------------- * Print-Styles * -------------------------------------------------------- */ diff --git a/public/styles/reminders.css b/public/styles/reminders.css index a7f6cf2..f9e0d50 100644 --- a/public/styles/reminders.css +++ b/public/styles/reminders.css @@ -37,7 +37,7 @@ display: flex; align-items: center; flex-shrink: 0; - color: var(--color-accent); + color: var(--module-reminders); } .toast__reminder-text { diff --git a/public/styles/tokens.css b/public/styles/tokens.css index fbcd122..bc41fad 100644 --- a/public/styles/tokens.css +++ b/public/styles/tokens.css @@ -170,8 +170,10 @@ --module-contacts: var(--_module-contacts); /* Kräftiges Blau - Kontakte */ --_module-budget: #0F766E; --module-budget: var(--_module-budget); /* Teal-700 - Finanzen, Stabilität */ - --_module-settings: #6E7781; - --module-settings: var(--_module-settings); /* Grau - Konfiguration */ + --_module-settings: #6E7781; + --module-settings: var(--_module-settings); /* Grau - Konfiguration */ + --_module-reminders: #0E7490; + --module-reminders: var(--_module-reminders); /* Cyan-700 - Erinnerungen, 6.3:1 auf weiß — WCAG AA */ /* -------------------------------------------------------- * 5. Farben - Mahlzeit-Typen @@ -405,6 +407,7 @@ --glass-tint-strength: var(--_glass-tint-strength); /* b) Blur-Stufen */ + --blur-2xs: blur(2px); --blur-xs: blur(4px); --blur-sm: blur(8px); --blur-md: blur(16px); @@ -524,8 +527,9 @@ --_module-shopping: #F472B6; --_module-notes: #FCD34D; --_module-contacts: #60A5FA; - --_module-budget: #2DD4BF; - --_module-settings: #94A3B8; + --_module-budget: #2DD4BF; + --_module-settings: #94A3B8; + --_module-reminders: #22D3EE; /* Cyan-400 */ --_meal-breakfast: #F59E0B; --_meal-breakfast-light: #332400; @@ -627,8 +631,9 @@ --_module-shopping: #F472B6; /* Pink-400 */ --_module-notes: #FCD34D; --_module-contacts: #60A5FA; - --_module-budget: #2DD4BF; /* Teal-400 */ - --_module-settings: #94A3B8; + --_module-budget: #2DD4BF; /* Teal-400 */ + --_module-settings: #94A3B8; + --_module-reminders: #22D3EE; /* Cyan-400 */ /* Mahlzeit-Typ */ --_meal-breakfast: #F59E0B; @@ -692,6 +697,7 @@ --glass-highlight: transparent; --glass-highlight-subtle: transparent; --glass-tint-strength: 0%; + --blur-2xs: blur(0px); --blur-xs: blur(0px); --blur-sm: blur(0px); --blur-md: blur(0px); @@ -716,6 +722,7 @@ --glass-border-subtle: var(--color-text-secondary); --glass-highlight: transparent; --glass-highlight-subtle: transparent; + --blur-2xs: blur(0px); --blur-xs: blur(0px); --blur-sm: blur(0px); --blur-md: blur(0px); From 2e054a6cc481798d4a17399cd12078d668145885 Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Sun, 26 Apr 2026 08:49:05 +0200 Subject: [PATCH 3/8] chore: release v0.24.4 --- CHANGELOG.md | 8 +++++++ package-lock.json | 4 ++-- package.json | 2 +- public/styles/layout.css | 46 ++++++++++++++++++++++++++++++++++++++++ public/styles/tokens.css | 2 +- 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c04ca29..024a8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [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 diff --git a/package-lock.json b/package-lock.json index 97f781d..0daf68e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.24.3", + "version": "0.24.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.24.3", + "version": "0.24.4", "license": "MIT", "dependencies": { "bcrypt": "^6.0.0", diff --git a/package.json b/package.json index 047b9ee..0913f12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.24.3", + "version": "0.24.4", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module", diff --git a/public/styles/layout.css b/public/styles/layout.css index 33949d7..87faf07 100755 --- a/public/styles/layout.css +++ b/public/styles/layout.css @@ -2025,6 +2025,52 @@ button svg { pointer-events: none; } /* Textarea: vertikale Größenänderung ist nutzbar */ textarea.input { resize: vertical; } +/* -------------------------------------------------------- + * High Contrast (prefers-contrast: more) + * Tokens in tokens.css stellen bereits opake Glass-Werte bereit. + * Hier kommen komponentenspezifische Korrekturen hinzu. + * -------------------------------------------------------- */ +@media (prefers-contrast: more) { + /* Fokus: dicker und weiter versetzt */ + :focus-visible { + outline-width: 3px; + outline-offset: 4px; + } + + /* Ghost- und Secondary-Buttons: explizite Umrandung */ + .btn--ghost, + .btn--secondary { + border: 1.5px solid currentColor; + } + + .btn--ghost:hover { + background-color: var(--color-surface-3); + } + + /* Karten: Schatten entfernen, Border verstärken */ + .card { + box-shadow: none; + border: 1px solid var(--color-border); + } + + .card--flat { + border-color: var(--color-text-secondary); + } + + /* Formulareingaben: kräftigere Border */ + .input, + .form-input { + border-color: var(--color-text-primary); + border-width: 2px; + } + + /* Aktiver Nav-Eintrag: zusätzliche Unterstreichung als farb-unabhängiger Indikator */ + .nav-item[aria-current="page"] { + text-decoration: underline; + text-underline-offset: 3px; + } +} + /* -------------------------------------------------------- * Windows High Contrast / Forced Colors * -------------------------------------------------------- */ diff --git a/public/styles/tokens.css b/public/styles/tokens.css index bc41fad..358d655 100644 --- a/public/styles/tokens.css +++ b/public/styles/tokens.css @@ -324,7 +324,7 @@ --nav-height-mobile: 56px; --nav-bottom-height: calc(var(--nav-height-mobile) + 12px); /* scroll (56px) + dots-indicator (12px) */ --sidebar-width: 56px; /* collapsed icon-only (1024–1279px) */ - --sidebar-width-expanded: 220px; /* full sidebar (1280px+), max 240px laut Spec */ + --sidebar-width-expanded: 220px; /* full sidebar (1440px+), max 240px laut Spec */ --content-max-width: 1280px; --content-max-width-narrow: 720px; --cal-hour-height: 56px; From cd68bbfae7370e5bb1207718888dfc8f314b8dcd Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Sun, 26 Apr 2026 08:57:21 +0200 Subject: [PATCH 4/8] fix: remove CDN swagger UI, revert CSP, translate apiToken i18n keys to German - Delete public/doc-assets/swagger.html and swagger-init.js (CDN dependency violates project constraints) - Remove /docs route from server/index.js - Revert styleSrc and fontSrc in CSP to not include cdn.jsdelivr.net - Translate all 22 settings.apiToken* keys in de.json from English to German Co-Authored-By: Claude Sonnet 4.6 --- .codex | 0 public/doc-assets/swagger-init.js | 11 -------- public/doc-assets/swagger.html | 37 -------------------------- public/locales/de.json | 44 +++++++++++++++---------------- server/index.js | 7 ++--- 5 files changed, 24 insertions(+), 75 deletions(-) delete mode 100644 .codex delete mode 100644 public/doc-assets/swagger-init.js delete mode 100644 public/doc-assets/swagger.html diff --git a/.codex b/.codex deleted file mode 100644 index e69de29..0000000 diff --git a/public/doc-assets/swagger-init.js b/public/doc-assets/swagger-init.js deleted file mode 100644 index 75d47d8..0000000 --- a/public/doc-assets/swagger-init.js +++ /dev/null @@ -1,11 +0,0 @@ -window.addEventListener('DOMContentLoaded', () => { - window.ui = window.SwaggerUIBundle({ - url: '/openapi.json', - dom_id: '#swagger-ui', - deepLinking: true, - docExpansion: 'list', - persistAuthorization: true, - displayRequestDuration: true, - filter: true, - }); -}); diff --git a/public/doc-assets/swagger.html b/public/doc-assets/swagger.html deleted file mode 100644 index 0e9abd9..0000000 --- a/public/doc-assets/swagger.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Oikos API Docs - - - - - - -
- Oikos API Documentation - -
-
- - diff --git a/public/locales/de.json b/public/locales/de.json index 804c6d3..82ba5a1 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -630,28 +630,28 @@ "currencyLabel": "Währung", "currencyHint": "Legt die Währung für den gesamten Budget-Bereich fest.", "currencySaved": "Währung gespeichert.", - "apiTokensTitle": "API Tokens", - "apiTokensCardTitle": "Access Tokens", - "apiTokensHint": "Create API tokens for external integrations. The full token is shown only once after creation.", - "apiTokenNameLabel": "Token name", - "apiTokenExpiresLabel": "Expiration date", - "apiTokenExpiresHint": "Leave empty to create a token without expiration.", - "apiTokenCreatedLabel": "New API token", - "apiTokenCreatedHint": "Store this token securely. It cannot be shown again.", - "apiTokenCreate": "Create token", - "apiTokenInvalidExpiration": "Please enter a valid expiration date.", - "apiTokenCreatedToast": "API token created.", - "apiTokenRevokedToast": "API token revoked.", - "apiTokenRevokeConfirm": "Revoke API token \"{{name}}\"?", - "apiTokenRevoke": "Revoke token", - "apiTokenRevoked": "Revoked", - "apiTokenExpired": "Expired", - "apiTokenActive": "Active", - "apiTokenPrefix": "Prefix", - "apiTokenExpires": "Expires", - "apiTokenNeverExpires": "No expiration", - "apiTokenLastUsed": "Last used", - "apiTokenNeverUsed": "Never used", + "apiTokensTitle": "API-Tokens", + "apiTokensCardTitle": "Zugriffstoken", + "apiTokensHint": "Erstelle API-Tokens für externe Integrationen. Der vollständige Token wird nach der Erstellung nur einmal angezeigt.", + "apiTokenNameLabel": "Tokenname", + "apiTokenExpiresLabel": "Ablaufdatum", + "apiTokenExpiresHint": "Leer lassen, um einen Token ohne Ablaufdatum zu erstellen.", + "apiTokenCreatedLabel": "Neuer API-Token", + "apiTokenCreatedHint": "Speichere diesen Token sicher. Er kann nicht erneut angezeigt werden.", + "apiTokenCreate": "Token erstellen", + "apiTokenInvalidExpiration": "Bitte gib ein gültiges Ablaufdatum ein.", + "apiTokenCreatedToast": "API-Token erstellt.", + "apiTokenRevokedToast": "API-Token widerrufen.", + "apiTokenRevokeConfirm": "API-Token \"{{name}}\" widerrufen?", + "apiTokenRevoke": "Token widerrufen", + "apiTokenRevoked": "Widerrufen", + "apiTokenExpired": "Abgelaufen", + "apiTokenActive": "Aktiv", + "apiTokenPrefix": "Präfix", + "apiTokenExpires": "Läuft ab", + "apiTokenNeverExpires": "Kein Ablaufdatum", + "apiTokenLastUsed": "Zuletzt verwendet", + "apiTokenNeverUsed": "Nie verwendet", "ics": { "title": "ICS-Abonnements", "add": "Abonnement hinzufügen", diff --git a/server/index.js b/server/index.js index 77307a8..d09af0e 100644 --- a/server/index.js +++ b/server/index.js @@ -57,10 +57,10 @@ app.use(helmet({ // Alpine.js CDN (optional, falls verwendet) 'https://cdn.jsdelivr.net', ], - styleSrc: ["'self'", "'unsafe-inline'", 'https://cdn.jsdelivr.net'], + styleSrc: ["'self'", "'unsafe-inline'"], imgSrc: ["'self'", 'data:'], connectSrc: ["'self'"], - fontSrc: ["'self'", 'data:', 'https://cdn.jsdelivr.net'], + fontSrc: ["'self'"], objectSrc: ["'none'"], frameSrc: ["'none'"], // upgrade-insecure-requests nur mit HTTPS aktivieren @@ -176,9 +176,6 @@ function sendOpenApi(req, res) { app.get('/api/v1/openapi.json', sendOpenApi); app.get('/openapi.json', sendOpenApi); -app.get('/docs', (_req, res) => { - res.sendFile(path.join(import.meta.dirname, '..', 'public', 'doc-assets', 'swagger.html')); -}); // Alle weiteren API-Routen erfordern Authentifizierung + CSRF-Schutz app.use('/api/v1', requireAuth); From 777e617b7407645fa6a1b98f012deef34eea301f Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Sun, 26 Apr 2026 09:00:15 +0200 Subject: [PATCH 5/8] chore: release v0.25.0 --- CHANGELOG.md | 11 +++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 024a8a0..08ebefc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [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 diff --git a/package-lock.json b/package-lock.json index 0daf68e..364d291 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.24.4", + "version": "0.25.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.24.4", + "version": "0.25.0", "license": "MIT", "dependencies": { "bcrypt": "^6.0.0", diff --git a/package.json b/package.json index 0913f12..bb88d1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.24.4", + "version": "0.25.0", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module", From 3bfda59fc03bf535e07961a63a9b80fedf30ecd0 Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Sun, 26 Apr 2026 09:03:45 +0200 Subject: [PATCH 6/8] fix: compact widget empty states, view transitions for reordering, widget body padding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - widget__empty: column → row layout, icon 28→20px, padding space-5 → space-3 saves ~40px vertical space per empty widget on mobile, keeps populated widgets visible above the fold - widget__body: bottom padding space-3 → space-4 for slightly more breathing room - rebuildList() now uses document.startViewTransition with prefers-reduced-motion guard; each customize-row gets a stable view-transition-name for smooth reorder animation without a JS animation library Co-Authored-By: Claude Sonnet 4.6 --- docs/ux-audit-plan.md | 4 ++-- public/pages/dashboard.js | 18 +++++++++++++----- public/styles/dashboard.css | 16 ++++++++-------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/docs/ux-audit-plan.md b/docs/ux-audit-plan.md index 14d7e92..02cf108 100644 --- a/docs/ux-audit-plan.md +++ b/docs/ux-audit-plan.md @@ -47,5 +47,5 @@ 2. **Lack of Visual Feedback in Customization**: Reordering widgets in the customize modal (`rebuildList()`) happens instantly without transition, feeling jarring. ### Implementation Steps -- [ ] **Compact Empty States (`dashboard.js`)**: Offen — `.widget__empty` hat bereits reduziertes Padding (`space-5`), aber kein echtes Row-Layout. Niedrige Priorität. -- [ ] **Animate Widget Reordering (`dashboard.js`)**: Offen — View Transition API wäre sinnvoll, aber kein Bug. Niedrige Priorität. +- [x] **Compact Empty States (`dashboard.css`)**: `.widget__empty` auf horizontales Row-Layout umgestellt, Icon 28→20px, Padding reduziert — spart ~40px vertikalen Platz pro leerem Widget. +- [x] **Animate Widget Reordering (`dashboard.js`)**: `rebuildList()` nutzt nun `document.startViewTransition()` mit `prefers-reduced-motion`-Guard und `view-transition-name` je Row. diff --git a/public/pages/dashboard.js b/public/pages/dashboard.js index 00fa84e..5a706b9 100644 --- a/public/pages/dashboard.js +++ b/public/pages/dashboard.js @@ -546,7 +546,7 @@ function openCustomizeModal(currentConfig, onSave) { const isFirst = i === 0; const isLast = i === draft.length - 1; return ` -
+