KolektivComputer / KolektivComputer/kalendee
Calendar providers: ICS/webcal subscription imports
- Dominant language
- Kotlin
- Stars
- 0
- Forks
- 0
- Avg merge
- 11h 20m
- Merged PRs (30d)
- 23
Description
## Context
ICS subscriptions are step 4 of the recommended order: read-only, no OAuth, small effort, and the only integration path for providers without public calendar APIs (Proton, Tutanota, HEY, Yahoo, AOL, Samsung, Naver) plus any `webcal://` or "publish calendar" URL. M3 in `docs/external-calendars.md` lists this as optional, but it delivers value while the API adapters mature. Polling uses HTTP `ETag`/`Last-Modified` validators, and imported events become ordinary mirrored rows.
## Tasks
- [ ] New `ics` provider/connection type with a secret URL stored via `TokenVault`
- [ ] Normalize `webcal://` → `https://`, follow redirects with an SSRF guard (block loopback/private ranges by default)
- [ ] Parse ICS with KalDAV's iCalendar reader; map VEVENTs to mirrored events (master-only recurrence best effort)
- [ ] Conditional polling with `ETag`/`Last-Modified` + `If-None-Match`/`If-Modified-Since`; persist validators on `external_calendars`
- [ ] Detect deletions between polls via UID set diff; calendar stays read-only
- [ ] Subscription management in Connected Accounts (add URL, rename, refresh, remove)
- [ ] Handle non-2xx/timeouts with `last_error` + backoff; never retry hot
- [ ] Tests: parser mapping, conditional GET, UID-diff deletion, `webcal` normalization
## References
- `docs/external-calendars.md` — provider matrix (ICS row and no-public-API table), M3
- `server/src/main/kotlin/dev/kolektiv/kalendee/oauth/CalendarProvider.kt`
- #7 (KalDAV iCalendar parser), #2 (Connected Accounts UI), #1 (mirror mapping)
## Dependencies
- Can land without OAuth credentials; UI slots into #2.
- Uses the iCalendar parser from #7; event mapping overlaps #1.
Contributor guide
Assessment
This issue has not been assessed yet.