refactor: add sync-source state and read-only import guard #444

Closed
opened 2026-05-13 18:42:17 +00:00 by barrettruth · 0 comments
Owner

Parent: #123
Related: #290, #291, #442

Problem

Google Tasks and Google Calendar should share one multi-sync model instead of growing separate metadata blobs and one-off read-only checks.

The product direction is now: Google-imported rows are normal Delta task rows, but they are read-only to the user. Only the provider sync engine may mutate fields imported from Google. This needs to be enforced below the frontend so API routes, server actions, keyboard shortcuts, drag/resize, recurrence edits, and CLI paths cannot mutate imported rows by accident.

Decisions

  • Use a durable per-source sync-state table rather than only integration_configs.metadata.
  • Keep account-level Google profile/token metadata in the existing Google integration config.
  • Model provider collections as sync sources, so Google Task lists, Google calendars, and future CalDAV/Apple-style calendars can share the same shape.
  • Read-only protection must be provider-agnostic and driven by source/external-link state.
  • Sync engines may update imported fields and external-link/source metadata; normal user mutation paths must be blocked.
  • Attempted edits should produce a warning/yellow operator-visible message through UI surfaces, but the core guard is authoritative.

Suggested storage shape

Exact names can change during implementation, but the durable source row should represent:

  • user id
  • provider id, e.g. google
  • source kind, e.g. google_tasks_list, google_calendar
  • source id from the provider
  • display title
  • enabled flag
  • default category/category mapping
  • sync cursor/token
  • last sync timestamp
  • last result summary
  • last error
  • provider source metadata JSON, such as access role, hidden/selected flags, colors, time zone, watch-channel fields later

Acceptance criteria

  • A migration and schema helpers add the per-source sync-state storage.
  • Existing Google account OAuth/token storage remains in integration_configs.
  • A provider-agnostic helper can identify read-only imported tasks from external-link/source state.
  • Core task mutation paths can reject user mutations to read-only imported tasks.
  • Sync-engine code has an explicit path to update imported rows without going through user mutation checks.
  • External-link metadata updates remain allowed for sync bookkeeping.
  • Tests cover user mutation blocked, sync mutation allowed, and source state CRUD.

Non-goals

  • Do not add Google Calendar pull here.
  • Do not finalize every source-indicator icon or dense UI treatment here.
  • Do not add scheduled/background sync here.
Parent: #123 Related: #290, #291, #442 ## Problem Google Tasks and Google Calendar should share one multi-sync model instead of growing separate metadata blobs and one-off read-only checks. The product direction is now: Google-imported rows are normal Delta task rows, but they are read-only to the user. Only the provider sync engine may mutate fields imported from Google. This needs to be enforced below the frontend so API routes, server actions, keyboard shortcuts, drag/resize, recurrence edits, and CLI paths cannot mutate imported rows by accident. ## Decisions - Use a durable per-source sync-state table rather than only `integration_configs.metadata`. - Keep account-level Google profile/token metadata in the existing Google integration config. - Model provider collections as sync sources, so Google Task lists, Google calendars, and future CalDAV/Apple-style calendars can share the same shape. - Read-only protection must be provider-agnostic and driven by source/external-link state. - Sync engines may update imported fields and external-link/source metadata; normal user mutation paths must be blocked. - Attempted edits should produce a warning/yellow operator-visible message through UI surfaces, but the core guard is authoritative. ## Suggested storage shape Exact names can change during implementation, but the durable source row should represent: - user id - provider id, e.g. `google` - source kind, e.g. `google_tasks_list`, `google_calendar` - source id from the provider - display title - enabled flag - default category/category mapping - sync cursor/token - last sync timestamp - last result summary - last error - provider source metadata JSON, such as access role, hidden/selected flags, colors, time zone, watch-channel fields later ## Acceptance criteria - A migration and schema helpers add the per-source sync-state storage. - Existing Google account OAuth/token storage remains in `integration_configs`. - A provider-agnostic helper can identify read-only imported tasks from external-link/source state. - Core task mutation paths can reject user mutations to read-only imported tasks. - Sync-engine code has an explicit path to update imported rows without going through user mutation checks. - External-link metadata updates remain allowed for sync bookkeeping. - Tests cover user mutation blocked, sync mutation allowed, and source state CRUD. ## Non-goals - Do not add Google Calendar pull here. - Do not finalize every source-indicator icon or dense UI treatment here. - Do not add scheduled/background sync here.
barrettruth added this to the v0.1.0 milestone 2026-05-13 18:42:17 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
barrettruth/delta#444
No description provided.