From a8a50d31c5bfac1b4f7a4aa74e25f03e70992089 Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Tue, 21 Apr 2026 06:52:52 +0200 Subject: [PATCH] chore: release v0.20.39 --- CHANGELOG.md | 6 ++++++ README.md | 2 +- docs/SPEC.md | 22 ++++++++++++++++++++-- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f967259..4b752d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.20.39] - 2026-04-21 + +### Changed +- `docs/SPEC.md`: document `ics` as a valid `external_source` value, add `subscription_id` and `user_modified` columns to Calendar Events data model, add ICS Subscriptions table definition, expand Calendar module section with ICS subscription feature details, update Settings section +- `README.md`: update Calendar Sync highlight to mention ICS/webcal URL subscriptions + ## [0.20.38] - 2026-04-21 ### Added diff --git a/README.md b/README.md index 73d39da..a3a447f 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ **Meal Planning:** Weekly drag-and-drop planner with ingredient lists and shopping export -**Calendar Sync:** Two-way sync with Google Calendar (OAuth) and Apple iCloud (CalDAV) +**Calendar Sync:** Two-way sync with Google Calendar (OAuth) and Apple iCloud (CalDAV); subscribe to any public ICS/webcal URL with per-subscription color, private/shared visibility, and automatic sync **Budget Tracking:** Income and expenses, recurring entries, configurable currency (15 currencies), monthly trends, CSV export diff --git a/docs/SPEC.md b/docs/SPEC.md index acdd100..2987266 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -90,8 +90,10 @@ Custom, household-wide category list for shopping items. Replaces the old hardco | assigned_to | INTEGER | FK → Users | | created_by | INTEGER | FK → Users, NOT NULL | | external_calendar_id | TEXT | ID from external calendar | -| external_source | TEXT | local, google, apple | +| external_source | TEXT | local, google, apple, ics | | recurrence_rule | TEXT | iCal RRULE | +| subscription_id | INTEGER | FK → ICS Subscriptions (CASCADE delete) | +| user_modified | INTEGER | 0/1 — prevents sync overwrite when 1 | ### Notes | Column | Type | Constraint | @@ -133,6 +135,21 @@ Stores instances of a recurring entry deleted by the user so they are not re-gen | month | TEXT | YYYY-MM, NOT NULL | | PRIMARY KEY | | (parent_id, month) | +### ICS Subscriptions +External calendar feeds subscribed by users (read-only, auto-synced). + +| Column | Type | Constraint | +|--------|------|-----------| +| name | TEXT | NOT NULL | +| url | TEXT | NOT NULL (https:// or webcal://) | +| color | TEXT | HEX, default #6366f1 | +| shared | INTEGER | 0/1 — visible to all family members when 1 | +| created_by | INTEGER | FK → Users (SET NULL on delete) | +| etag | TEXT | HTTP ETag for conditional fetch | +| last_modified | TEXT | HTTP Last-Modified for conditional fetch | +| last_sync | TEXT | ISO timestamp of last successful sync | +| created_at | TEXT | ISO timestamp | + ### Sync Config Key-value table for OAuth tokens and CalDAV credentials. @@ -206,6 +223,7 @@ Weekly view (Mon–Sun), slots: breakfast / lunch / dinner / snack. - Recurring via iCal RRULE - **Google Calendar:** OAuth 2.0, Calendar API v3, two-way sync - **Apple Calendar:** CalDAV (tsdav), two-way sync +- **ICS Subscriptions:** Subscribe to any public ICS/webcal URL (e.g. public holidays, sports schedules). Per-subscription color, private/shared visibility, manual "Sync now" and automatic sync on the shared interval. RRULE events expanded into a rolling ±6/+12 month window. SSRF-protected (DNS pre-resolution), ETag/Last-Modified conditional fetch, 10 MB limit, 15 s timeout. User-edited events are protected from being overwritten (`user_modified`); a "Reset to original" link restores them. - Configurable sync interval (default 15 min) - External events visually distinguishable - Conflicts: external event wins, local additions are preserved @@ -244,7 +262,7 @@ User management and app configuration. Logged-in users only. - **Profile:** change display name, avatar color, password - **User management (admin):** create new users, edit/delete existing users, assign roles (admin/member) -- **Calendar integration:** connect/disconnect Google Calendar OAuth, store Apple Calendar (CalDAV) credentials, configure sync interval +- **Calendar integration:** connect/disconnect Google Calendar OAuth, store Apple Calendar (CalDAV) credentials, configure sync interval; manage ICS URL subscriptions (add, delete, sync now, set color and visibility) - **Weather:** configure OpenWeatherMap location - **Language:** System (follows `navigator.language`), German, English, Spanish, French, Italian, Swedish, Greek, Russian, Turkish, Chinese - via `oikos-locale-picker` web component; switch without page reload - **Tab navigation:** Settings is organized in six tabs (General, Meals, Budget, Shopping, Calendar, Account). Sticky tab bar, active tab persists in sessionStorage, Calendar tab auto-activates after OAuth callbacks. diff --git a/package-lock.json b/package-lock.json index eee61b0..9b8221f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.20.37", + "version": "0.20.39", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.20.37", + "version": "0.20.39", "license": "MIT", "dependencies": { "bcrypt": "^6.0.0", diff --git a/package.json b/package.json index 84e0acb..4f40c69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.20.38", + "version": "0.20.39", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module",