- Shipped
- 2026年11月15日 10:00 UTC
- Author
- Kamo
- Commit
- 3b85588
Settings › Email › CalDAV/CardDAV saved outside connections and showed "Last synced" for a sync that fetched nothing (DaemonService's jobs bumped counters and marked everything IDLE; the provider classes were TODOs). EmailService now syncs them for real (groupware/sync): - CalDAV/CardDAV: discovery (address → principal → home set → collections, with /.well-known fallback, a pasted single-calendar address works), CTag/sync-token check, calendar-query ETag listing (last 366 days on), multiget of what changed, PUT/DELETE with If-Match/If-None-Match. iCloud defaults its addresses. - Google Calendar + People, Microsoft Graph calendars + contacts on the grant the /oauth flow stores; tokens refreshed (and rotated refresh tokens kept) with a write that only replaces the exact blob it refreshed. - Events land through IcsImportService.upsert (series, exceptions, EXDATEs) and contacts through ContactService + ContactDetailStore — no invitations, no reminders, no raw table writes. - Bookkeeping per collection/item (new groupware_sync_* tables) gives updates, deletions and two-way: pull first (outside copy wins a tie), then push Kamo edits/creates/deletes when the integration is two-way and the collection writable. Guards: nothing removed on a failed or suspiciously empty listing, nothing Kamo did not import, nothing that only aged out of the window; a pass that would delete most of a collection out there is refused. - Status is honest: SYNCING while running, IDLE + lastSyncedAt only after a full fetch, ERROR + plain-words errorMessage otherwise; written column-by-column so a member's edit mid-pass survives. Per-collection lastError and counts are in the settings payload (syncSupported, calendarsSynced, eventsSynced, addressBooksSynced, contactsSynced, collections[]). - Scheduling: **************** (DaemonService's clock) and /integrations/{id} (Sync Now via daemon.sync.trigger, local fallback without NATS); per-integration SingletonTaskRunner lease so pods never double-run. - Test Connection now signs in and lists; member rows record their organization; deleting an integration detaches (keeps) what was synced; outside addresses must be https to a public host (no cluster/SSRF reach); credentials never logged. - Removed the dead TODO provider stubs and their unused refreshers.
