Repository navigation
feat: compatibility hints for sync, multiget and DELETE quirks - #822
Merged
Merged
Conversation
Infomaniak (SabreDAV) answers a member removed since the last sync token with a response-level 404 and an empty propstat with 418. The legacy parser validated that propstat and raised, so every sync after a deletion failed. A 404 response now has its propstats dropped. Prompt: [follow-up on a handover document from an earlier session, which reported the 418 issue:] caldav library bugs should be fixed - if it's too heavy lifting for an already overloaded session the right fix is to file it. Followup-Prompt: Other session should be done now, it's at the end of the push gate logic. When doing changes in the caldav library, please do it at the top of the pull request it makes, to avoid having to rebase pull requests and rerun pipelines Followup-Prompt: yes [go ahead with the plan, including fixing the 418 bug] Followup-Prompt: the other session has merged #820. Create a new PR. (...) [#820 is #820] Assisted-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
Three compatibility features, each with a probe in caldav-server-tester: delete.if-match (SOGo deletes on a stale If-Match), save-load.event.floating (SOGo pins a floating event to TZID=Etc/UTC) and save-load.icalendar.attendee-params (SOGo adds RSVP=TRUE). The SOGo profile gets the measured verdicts. Prompt: work on /tmp-handover-sogo-hints-2026-10-23.md (sic) [a handover note asking for probes and caldav hints for three SOGo behaviours found by calendaring's conformance suite: DELETE ignoring a stale If-Match, floating event times stored as UTC, ATTENDEE parameters rewritten] Assisted-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
Compatibility features for behaviours a sync client depends on, as found by calendaring-sync: delete.missing(.if-match), the sync-token initial-sync, created-and-deleted and recreated features, multiget (missing-href, limit), propfind.limit and save.etag.matches-stored. The Stalwart test container gets WebDav.maxResults 50, so the limits can be probed with few objects. Profiles are not updated yet. Prompt: Have a look into https://github.com/PyCalendar/calendaring-sync/blob/c40782bc7afe7b350fe63bf27ef13374c280ea8b/docs/reference/server-compatibility.rst and see if there is anything we should add to the tests from that page Followup-Prompt: All of them should be probed. Please consider what feature tags we should put the results under and open up suggestions in my editor. Prompts (comments made inline in the document while reviewing it): > (on the DELETE with If-Match on a missing object) We don't have any other features under delete.* yet. There is a sync-token.delete and delete-calendarxo (sic) ... but I have no better ideas than the recommended. It's Robur that is the special case with non-existing-raises-not-found.object - does robur return 404 when trying to delete the object? If it returns 403, then use the alternative. > (on calendar-multiget) The check for stalwarts (sic) page problem should also be added > (on the initial sync) We have a sync-token.limit.initial-sync, should it be renamed sync-token.initial-sync.limit ? > (on the order of work) ok > check the external servers too, defined under ~/caldav-server-tester Followup-Prompt: (answer to a clarifying question) Keep the name [sync-token.limit.initial-sync] Followup-Prompt: (answer to a clarifying question) The checker code should be generic. If testing with 60 items and the limit was set down to 50 in the stalwart image, then we're confirming the problem with stalwart, but we're not checking anything on any other servers. I think we lower it in docker and have an environment variable to set the number of items probed. (wasn't there also a limit header or xml attribute that could be sent?) Followup-Prompt: if foo.bar is unsupported, but foo.bar.zoo is suppored (sic), then that may be a hint that the hierarchy is not well-enough thought through. foo.bar.zoo should typically be dependent on foo.bar Followup-Prompt: (answer to a clarifying question) save.etag.matches-stored Followup-Prompt: (summary: open the handover document about the sync probes in the editor; inline comments follow) Prompts (comments made inline in the document while reviewing it): > (on dropping the child feature) This makes sense - except, when too many different behaviours gets (sic) packed into one feature it often makes sense to split it up into children. The problem here is that we're potentially dealing with a child that is "Not Applicable" if the parent is unsupported, can be "Not Applicable" if the parent is supported and can never be unsupported, only broken. This simply does not fit into the feature hiearchy (sic) as it was designed. There is no grading "Not Applicable". Maybe the solution is to add such a grading. > matches-stored ... that may make sense. "supported" if stored is not rewritten. "supported" if stored is rewritten and the etag is weak or not given. "broken" if stored is rewritten and etag is strong. Am I right? > (on servers rewriting with a strong ETag) So they would get "broken" > (on servers rewriting without a strong ETag) And they would get "supported". > (on servers storing as sent) And they would also get "supported". Followup-Prompt: yes [go ahead with broken for a rewrite under a strong ETag, then the rest of the handover] Assisted-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
What caldav-server-tester measured on 22 servers for the features of the previous commit, as profile entries: DELETE If-Match broken or 412 on a missing object, missing hrefs left out of a multiget, the initial-sync, created-and-deleted and recreated quirks, Stalwart's limits, and the servers that rewrite an object under a strong ETag. Every entry was re-checked by a tester run against the profile. Infomaniak loses its ungraceful sync-token.delete: with the parser fix below this commit, its deletions sync fine. Prompt: (summary: open the handover document about the sync probes in the editor; inline comments follow) Prompts (comments made inline in the document while reviewing it): > matches-stored ... that may make sense. "supported" if stored is not rewritten. "supported" if stored is rewritten and the etag is weak or not given. "broken" if stored is rewritten and etag is strong. Am I right? > (on servers rewriting with a strong ETag) So they would get "broken" > (on Stalwart reporting created-and-deleted correctly, unlike calendaring-sync's page) Do more research, maybe? Report back in the pull request, tag sashank > (on the Infomaniak 418 finding) caldav library bugs should be fixed - if it's too heavy lifting for an already overloaded session the right fix is to file it. Followup-Prompt: yes [go ahead with broken for a rewrite under a strong ETag, then the rest of the handover, which lists writing these profiles as a next step] Assisted-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
save-load.event.floating named the time of calendaring-sync's example event (09:00 UTC); what SOGo does is pin any wall-clock time to UTC. delete.missing.if-match now says the conditional DELETE answers as the plain one does, as RFC 9110 section 13.2.1 has it and as the tester now grades it, rather than always 404. Prompt: [fix issues found during the review process] Prompts (comments made inline in the document while reviewing it): > (on grading delete.missing.if-match against the plain DELETE's answer) Make sure both `delete.missing` and `delete.missing.if-match` is (sic) checked. Assisted-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
This was referenced Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disclaimer: AI-generated code and text below the line, generated by Claude Opus 5.5, from the prompts:
(the commits carry the full prompt record)
Stacked on #821; review that first.
Compatibility features and server profiles for behaviours a sync client depends on, found by calendaring-sync's server compatibility page and measured with caldav-server-tester on 22 servers:
delete.if-match,save-load.event.floatingandsave-load.icalendar.attendee-params.delete.missinganddelete.missing.if-match.sync-token.initial-sync,sync-token.delete.created-and-deletedandsync-token.recreated.multiget.missing-href,multiget.limitandpropfind.limit.save.etag.matches-stored, a server rewriting what it stores while answering with a strong ETag.The Stalwart test container now runs with
WebDav.maxResults50, so the limits can be probed with few objects.Infomaniak loses its ungraceful
sync-token.deletehint: with #821 its deletions sync fine.