KolektivComputer / KolektivComputer/kalendee

OAuth M2: two-way writes, sync scheduler, and conflict handling

Open
#4 0 comments 0 reactions 1 assignee Claimed by @LizAinslie View on GitHub
c/enhancement c/feature i/gcal i/microsoft t/server
Dominant language
Kotlin
Stars
0
Forks
0
Avg merge
11h 20m
Merged PRs (30d)
23

Description

## Context

M1 delivers read-only mirrors; M2 in `docs/external-calendars.md` flips selected calendars to `sync_direction = 'push' | 'both'` and routes local writes through the provider. Local `events.etag` stays the optimistic-concurrency token while the provider `If-Match`/ETag lives in `external_etag`, with a scheduler driving periodic sync. This is where conflict handling and notification-on-state-change become real; it depends on M1's mapping and tombstone tables.

## Tasks

- [ ] Write-through create/update/delete in the calendar store for provider-managed calendars, honoring `sync_direction`
- [ ] Provider `If-Match`/ETag handling; persist provider result to `external_etag`/`external_updated_at` and bump local `etag` so existing client checks keep working
- [ ] Tombstone upload (`external_event_tombstones`) and remote-delete application
- [ ] Conflict policy: keep the local edit as a "(conflict)" copy and notify once per state change
- [ ] Block cross-provider `moveEvent` and unsupported recurrence edits
- [ ] `SyncService` scheduler: exponential backoff + jitter, per-connection mutex, manual "Sync now", honor `Retry-After`
- [ ] Per-connection status (last sync/error/`needs_reauth`) surfaced in settings and sidebar
- [ ] Tests: push mapping, conflict path, tombstone upload, backoff/jitter scheduling

## References

- `docs/external-calendars.md` — M2 section and cross-cutting risks (conflict handling, rate limits and retries)
- `server/src/main/kotlin/dev/kolektiv/kalendee/store/PostgresCalendarStore.kt`
- `server/src/main/kotlin/dev/kolektiv/kalendee/oauth/ConnectionService.kt`
- `server/src/main/resources/db/migration/V17__external_calendars.sql`
- `core/src/commonMain/kotlin/dev/kolektiv/kalendee/calendar/Recurrence.kt` — recurrence fidelity limits

## Dependencies

- Depends on #1 (M1 read-only mirror), which depends on branch `feat/oauth-foundation` — currently being restored.
- Honest two-way recurrence needs a real RRULE engine; until then two-way is limited to non-recurring/simple events.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.