[Task] Implement destructive synchronized-calendar remote move saga (deferred) #19

Open
opened 2026-07-20 14:42:13 +02:00 by zemion · 2 comments
Owner

Decision

The first release supports only explicit, non-destructive synchronized-calendar bulk modes:

  1. detach_keep_remote (synchronized → local) localizes the projection, clears sync-owned href/ETag metadata, and never deletes the remote collection or events.
  2. copy_to_remote (local → two-way synchronized) moves local desired state and enqueues durable, idempotent destination PUTs. Delivery, retry, conflict, dead-letter, and reconciliation state remain observable.

A synchronized → synchronized remote_move is deliberately deferred. The API must reject that mode rather than infer a remote delete.

Deferred Remote-Move Contract

A later remote_move must be an explicit destructive saga grouped by CalDAV resource. Every destination PUT must succeed or reconcile before any conditional source DELETE is released. Destination conflict or dead work blocks deletion. Cancellation before delete keeps both copies; after deletion starts, the batch resumes/reconciles and never rolls back through blind writes.

Remaining decisions for that later slice:

  • UID collision policy (recommended: preserve UID and surface a conflict).
  • Concurrent-edit behavior (recommended for v1: block edits while migrating).
  • Authorized roles, confirmation wording, and required evidence for destructive remote moves.

Current Acceptance Criteria

  • API and UI name the external consequence before execution.
  • Synchronized → local leaves the remote side untouched.
  • Local → synchronized uses the durable Calendar outbox and idempotent reconciliation.
  • Synchronized → synchronized remains explicitly rejected.
  • Tests cover safe-mode validation, local state, queued remote copy work, retries, and rejection of the deferred mode.

Later Remote-Move Acceptance Criteria

  • Migration batches expose phase, progress, conflicts, and durable idempotency.
  • Destination success is a dependency of source delete; retries and crashes cannot lose the only remote copy.
  • Conditional ETags protect source deletes and destination updates.
  • Tests cover duplicates, crash points, partial destination failure, collision, cancellation, concurrent remote edits, and reconciliation.
## Decision The first release supports only explicit, non-destructive synchronized-calendar bulk modes: 1. `detach_keep_remote` (synchronized → local) localizes the projection, clears sync-owned href/ETag metadata, and never deletes the remote collection or events. 2. `copy_to_remote` (local → two-way synchronized) moves local desired state and enqueues durable, idempotent destination PUTs. Delivery, retry, conflict, dead-letter, and reconciliation state remain observable. A synchronized → synchronized `remote_move` is deliberately deferred. The API must reject that mode rather than infer a remote delete. ## Deferred Remote-Move Contract A later `remote_move` must be an explicit destructive saga grouped by CalDAV resource. Every destination PUT must succeed or reconcile before any conditional source DELETE is released. Destination conflict or dead work blocks deletion. Cancellation before delete keeps both copies; after deletion starts, the batch resumes/reconciles and never rolls back through blind writes. Remaining decisions for that later slice: - UID collision policy (recommended: preserve UID and surface a conflict). - Concurrent-edit behavior (recommended for v1: block edits while migrating). - Authorized roles, confirmation wording, and required evidence for destructive remote moves. ## Current Acceptance Criteria - [x] API and UI name the external consequence before execution. - [x] Synchronized → local leaves the remote side untouched. - [x] Local → synchronized uses the durable Calendar outbox and idempotent reconciliation. - [x] Synchronized → synchronized remains explicitly rejected. - [x] Tests cover safe-mode validation, local state, queued remote copy work, retries, and rejection of the deferred mode. ## Later Remote-Move Acceptance Criteria - [ ] Migration batches expose phase, progress, conflicts, and durable idempotency. - [ ] Destination success is a dependency of source delete; retries and crashes cannot lose the only remote copy. - [ ] Conditional ETags protect source deletes and destination updates. - [ ] Tests cover duplicates, crash points, partial destination failure, collision, cancellation, concurrent remote edits, and reconciliation.
Author
Owner

Implemented the decision-free, non-destructive part locally:

  • synchronized -> local requires detach_keep_remote; projections move, sync metadata is cleared, the source is retired locally, undelivered outbox work is cancelled, and no remote DELETE is issued
  • local -> enabled two-way CalDAV requires copy_to_remote; the local move and durable destination PUT desired states commit atomically
  • local -> local remains compatible
  • mismatched actions, inbound-only targets, synchronized -> synchronized, and remote_move are explicitly rejected; the UI offers only supported targets and explains the consequence

Validation: full Calendar suite 81 tests, Ruff, structural i18n audit, translation-key verification, production WebUI build (5,634 modules), and diff check passed. This issue remains needs-info only for the destructive remote_move saga: collision policy, concurrent-edit policy, authority/confirmation/evidence, and whether it ships at all.

<!-- codex-progress-safe-bulk-moves-2026-07-20 --> Implemented the decision-free, non-destructive part locally: - synchronized -> local requires `detach_keep_remote`; projections move, sync metadata is cleared, the source is retired locally, undelivered outbox work is cancelled, and no remote DELETE is issued - local -> enabled two-way CalDAV requires `copy_to_remote`; the local move and durable destination PUT desired states commit atomically - local -> local remains compatible - mismatched actions, inbound-only targets, synchronized -> synchronized, and `remote_move` are explicitly rejected; the UI offers only supported targets and explains the consequence Validation: full Calendar suite 81 tests, Ruff, structural i18n audit, translation-key verification, production WebUI build (5,634 modules), and diff check passed. This issue remains needs-info only for the destructive `remote_move` saga: collision policy, concurrent-edit policy, authority/confirmation/evidence, and whether it ships at all.
zemion changed title from [Decision] Define loss-safe bulk moves involving synchronized calendars to [Task] Implement destructive synchronized-calendar remote move saga (deferred) 2026-07-20 16:42:35 +02:00
Author
Owner

Product decision (2026-07-20): accept the safe green baseline (detach_keep_remote and copy_to_remote) and defer destructive synchronized-to-synchronized moves. The open issue now tracks only that later saga; the current API must keep rejecting it.

Product decision (2026-07-20): accept the safe green baseline (`detach_keep_remote` and `copy_to_remote`) and defer destructive synchronized-to-synchronized moves. The open issue now tracks only that later saga; the current API must keep rejecting it.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GovOPlaN/govoplan-calendar#19
No description provided.