feat(sync): reconcile secondary Graph calendars

Read documented Graph v1 calendarView pages for secondary calendars and publish each finite window only after the complete bounded listing validates.

Add schema-v2 per-window event membership so moved-out occurrences are evicted without being mislabeled as remote tombstones, while overlapping windows retain shared instances.

Verified: 18/18 fresh normal, 18/18 -Werror, and 18/18 ASan/UBSan tests.
This commit is contained in:
2026-07-18 13:05:21 +01:00
parent 0582444c61
commit 98e07e287e
11 changed files with 1520 additions and 60 deletions

View File

@@ -169,17 +169,19 @@ immutable Graph IDs, parse strictly within fixed bounds, and keep credentials
out of errors. Access tokens are supplied per operation; Secret Service remains
the only persistent token store.
All Graph requests and opaque next/delta links must use HTTPS on
`graph.microsoft.com`. Primary-calendar event windows are half-open UTC ranges.
Each page, its tombstones, and its next or delta cursor commit atomically, so an
interrupted round resumes without advancing past durable data.
All Graph requests and opaque paging/delta links must use HTTPS on
`graph.microsoft.com`. Event windows are half-open UTC ranges. Primary-calendar
delta pages commit their changes and cursor atomically, so an interrupted round
resumes without advancing past durable data.
Stable Graph v1.0 documents `calendarView` delta only for the primary calendar.
Nocal therefore discovers all calendars but delta-syncs only the primary one;
it deliberately avoids beta and undocumented per-calendar routes. Secondary
calendars require a product decision between v1 full-window reconciliation with
explicit deletion semantics and a beta-specific delta implementation before
Outlook-equivalent coverage can be claimed. There is still no account UI/CLI
orchestration or live Microsoft credential integration, and remote writes
remain out of scope. The next phase is account setup and orchestration plus that
secondary-calendar decision.
Secondary-calendar reconciliation through stable Graph v1.0 reads the
documented per-calendar `calendarView`, finishes every page, and then atomically
replaces durable membership for that complete window. Events omitted from one
window lose cached instances only after no other complete window references
them; omission is not mislabeled as a remote deletion tombstone. This avoids
beta and undocumented delta routes, at the cost of refetching each secondary
window instead of incrementally updating it.
There is still no account UI/CLI orchestration or live Microsoft credential
integration, and remote writes remain out of scope. Account setup and
orchestration are next.