feat(calendar): delete tasks and events without losing audit history #117

Closed
opened 2026-09-23 23:45:28 +00:00 by yuris · 0 comments
Owner

Why

Cancelling a personal event currently writes STATUS:CANCELLED and retains its CalDAV resource. The resource still appears in the Life agenda and can remain visible in calendar clients, cluttering the user's calendar. Completing a task is not the same as removing an accidental or unwanted task. CalDAV supports deleting a resource; the local append-only journal can preserve the reason and before-state without requiring that resource to remain on the calendar. Do not conflate deleting a personal item with sending an organizer cancellation to meeting attendees.

Scope

  • Add explicit task delete and event delete CLI commands and authenticated write routes. Leave task complete/cancel and event cancel unchanged for users who want lifecycle history to remain visible on CalDAV.
  • Resolve the opaque item ID to a live resource within a configured collection, require the caller's current strong quoted ETag and a stable operation ID, and authorize the write. Do not accept an arbitrary URL, a wildcard, or a weak ETag.
  • Add conditional CalDAV DELETE with If-Match using the existing client request/origin safeguards. HTTP 412 is a conflict, not permission to reread and overwrite; never follow a redirect with credentials.
  • Durably prepare intent and a snapshot of the item, UID, href, actor, reason, and precondition before the remote request. After acknowledged deletion, append a deletion fact and remove current projections atomically, retaining historical events and operation records. Do not claim success when the remote write or journal commit is uncertain; operation get and existing recovery rules must surface uncertainty. A later 404 alone cannot prove which actor deleted an item.
  • Treat a resource containing a recurring master and overrides as one deletion unit. Require explicit series scope for a recurring resource; reject occurrence-only deletion rather than deleting the whole series. Do not delete mixed or foreign resources that cannot safely be attributed to the requested item.
  • Reads, sync, and agenda/tasks views must not resurrect an intentionally deleted projection. External deletions still reconcile as external observations rather than fabricated Life operations.

Acceptance

  • A real or local CalDAV mock confirms DELETE carries the exact If-Match and the resource becomes absent; agenda/tasks and item reads reflect absence while timeline and operation get retain evidence.
  • Tests cover event and task deletion, stale/missing/weak ETag, scope refusal on recurrence, replay with the same operation ID, unauthorized caller, and timeout or journal failure after uncertain dispatch. No second remote delete on blind retry.
  • Update API and calendar design docs to distinguish explicit deletion from cancellation. Add a focused live smoke path only against the dedicated smoke collection, with verified absence and cleanup; never test destructive behavior on personal/tasks production collections.

Release

This is an additive feature. Decide the release number after the work and gates pass; v0.2.4 is a possible next tag, not a precondition.

## Why Cancelling a personal event currently writes STATUS:CANCELLED and retains its CalDAV resource. The resource still appears in the Life agenda and can remain visible in calendar clients, cluttering the user's calendar. Completing a task is not the same as removing an accidental or unwanted task. CalDAV supports deleting a resource; the local append-only journal can preserve the reason and before-state without requiring that resource to remain on the calendar. Do not conflate deleting a personal item with sending an organizer cancellation to meeting attendees. ## Scope - Add explicit task delete and event delete CLI commands and authenticated write routes. Leave task complete/cancel and event cancel unchanged for users who want lifecycle history to remain visible on CalDAV. - Resolve the opaque item ID to a live resource within a configured collection, require the caller's current strong quoted ETag and a stable operation ID, and authorize the write. Do not accept an arbitrary URL, a wildcard, or a weak ETag. - Add conditional CalDAV DELETE with If-Match using the existing client request/origin safeguards. HTTP 412 is a conflict, not permission to reread and overwrite; never follow a redirect with credentials. - Durably prepare intent and a snapshot of the item, UID, href, actor, reason, and precondition before the remote request. After acknowledged deletion, append a deletion fact and remove current projections atomically, retaining historical events and operation records. Do not claim success when the remote write or journal commit is uncertain; operation get and existing recovery rules must surface uncertainty. A later 404 alone cannot prove which actor deleted an item. - Treat a resource containing a recurring master and overrides as one deletion unit. Require explicit series scope for a recurring resource; reject occurrence-only deletion rather than deleting the whole series. Do not delete mixed or foreign resources that cannot safely be attributed to the requested item. - Reads, sync, and agenda/tasks views must not resurrect an intentionally deleted projection. External deletions still reconcile as external observations rather than fabricated Life operations. ## Acceptance - A real or local CalDAV mock confirms DELETE carries the exact If-Match and the resource becomes absent; agenda/tasks and item reads reflect absence while timeline and operation get retain evidence. - Tests cover event and task deletion, stale/missing/weak ETag, scope refusal on recurrence, replay with the same operation ID, unauthorized caller, and timeout or journal failure after uncertain dispatch. No second remote delete on blind retry. - Update API and calendar design docs to distinguish explicit deletion from cancellation. Add a focused live smoke path only against the dedicated smoke collection, with verified absence and cleanup; never test destructive behavior on personal/tasks production collections. ## Release This is an additive feature. Decide the release number after the work and gates pass; v0.2.4 is a possible next tag, not a precondition.
yuris closed this issue 2026-09-24 07:42:31 +00:00
Sign in to join this conversation.
No labels
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
yuris/life-service#117
No description provided.