Files
nocal/docs/ROADMAP.md
Bernardo Magri 98e07e287e 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.
2026-07-18 13:05:21 +01:00

6.0 KiB

Roadmap

Foundation — current milestone

  • C++20 domain model and deterministic six-week month layout
  • Responsive, theme-native ANSI month view with keyboard navigation
  • Appointment focus, dense-day traversal, and full-frame detail reader
  • Validated add/edit/delete forms with confirmation and failure rollback
  • Guarded atomic .ics persistence, advisory locking, and round-trip tests
  • Bounded session undo/redo, exact external-change detection, and backup recovery
  • Windowed recurrence expansion, compatible RDATE, EXDATE, IANA TZID, and multi-day segment cues
  • Occurrence-aware appointment search with exact result-to-grid navigation
  • Session calendar toggles shared by month rendering, focus, and search
  • Read-only 42-day agenda with bounded recurrence and exact return navigation
  • Configurable week start with Monday-default CLI and consistent grid queries
  • Explicit atomic import/export with validation, collision refusal, and backups
  • Meson build, Nix development shell, desktop entry, and Hyprland launcher
  • Seeded sample data when explicitly requested, never silent data mutation

0.1 — complete local calendar

  • Advanced recurrence rule editing and detached RECURRENCE-ID overrides
  • Embedded VTIMEZONE support
  • Screen-reader-friendly linear view and full Unicode display-width handling

0.2 — durable cache and provider boundary — in progress

Completed cache foundation:

  • Provider-neutral SQLite WAL cache in a private local file
  • Versioned, all-or-nothing schema migrations
  • Raw provider payload retention, inactive calendars, and event tombstones
  • Per-calendar/window opaque cursors committed atomically with pulled pages
  • Normalized event instances for immutable snapshots
  • Reserved transactional outbox and conflict records for later remote writes

Completed HTTP/OAuth boundary:

  • Generic injected HTTP transport and deterministic fakes, with retries left to provider operations
  • Public-desktop OAuth authorization code design with PKCE S256, system browser, and loopback redirect
  • Multitenant Microsoft account audience and delegated least-privilege Calendars.Read; tenant policy may still require administrator consent or block user consent
  • No client secret in the open-source desktop binary

Completed concrete Linux adapters:

  • libcurl transport with verified TLS, bounded responses/timeouts, no automatic redirects/retries, and cleartext HTTP only for loopback tests
  • Shell-free xdg-open launcher and one-shot 127.0.0.1 callback receiver advertising http://localhost:<dynamic-port>/nocal/oauth/callback
  • Mobile/Desktop public-client registration at http://localhost/nocal/oauth/callback; Microsoft ignores localhost ports, while literal HTTP 127.0.0.1 needs a manifest edit and IPv6 loopback is not supported

Completed token/secret boundary:

  • Strict, bounded token JSON parsing with a required initial refresh token
  • Refresh-token rotation with retention of the previous token when a refresh response omits a replacement
  • Versioned libsecret payloads keyed by opaque local account IDs
  • Synchronous, cancellable Secret Service calls restricted to worker threads
  • Real isolated D-Bus/gnome-keyring integration tests
  • Explicit missing, locked, cancelled, and failure results; no connected account until the complete secret store succeeds
  • OAuth secrets only in Secret Service, never SQLite, logs, CLI arguments, or environment variables

Completed Microsoft Graph read phase:

  • Public desktop multitenant organizational/personal account support
  • Delegated User.Read for /me and Calendars.Read for calendars/events; tenant policy may still require approval or block user consent
  • Per-operation access tokens with persistent tokens retained only by Secret Service
  • Complete paged all-calendar discovery with atomic cache replacement and deterministic local IDs
  • Immutable Graph event IDs, strict bounded parsing, and credential-safe errors
  • HTTPS graph.microsoft.com-only opaque continuation/delta links
  • Half-open UTC event windows and per-page event/tombstone/cursor transactions
  • Resumable primary-calendar v1 delta synchronization

Completed secondary-calendar stable-v1 reconciliation:

  • Documented per-calendar calendarView reads with complete bounded paging
  • Schema-v2 durable per-window event membership
  • Atomic complete-window replacement after every page validates
  • Range omission distinguished from a remote deletion tombstone
  • Overlapping windows retain events until their last membership is removed
  • No beta or undocumented per-calendar delta dependency

Next provider-boundary slices:

  • Account setup and CLI/TUI orchestration with live credential integration
  • Generic SyncProvider integration and observable sync status

0.3 — CalDAV

  • Discovery and incremental sync for Nextcloud and standards-compliant servers
  • ETag-aware writes, offline mutation queue, conflict UI
  • TLS and failure-path integration tests

0.4 — hosted providers

  • Google Calendar adapter with incremental synchronization
  • Microsoft 365 read-only discovery and Graph delta synchronization, followed by ETag-aware remote writes after the conflict boundary is proven
  • Account/calendar management UI and per-calendar ANSI identity

The Graph read boundary uses stable v1 delta for the primary calendar and complete stable-v1 calendar views for secondary calendars; it deliberately avoids beta and undocumented per-calendar delta routes. No account UI/CLI orchestration or live Microsoft credential integration exists yet, and remote writes remain out of scope.

1.0 — distribution quality

  • Stable configuration/data format and documented recovery procedures
  • Nomarchy package, Hyprland defaults, man page, shell completions
  • Performance budgets exercised against large and adversarial calendars
  • Fuzzed iCalendar parser, accessibility review, translations

Quality gates

Every milestone requires clean warning-enabled builds, unit and integration tests, sanitizer runs, terminal-state recovery after signals/errors, no network access without explicit account setup, and no loss of unknown calendar data.