⚠️ This comment is AI-generated (Claude Sonnet 4.6 via Claude Code) on behalf of tobixen
The infrastructure for Schedule-Tag is half-built: the tag is received and cached, but
If-Schedule-Tag-Match is never sent on PUT requests, leaving attendee PARTSTAT updates
unprotected against racing organizer updates.
Full analysis and suggested implementation steps are in
docs/design/TODO_SCHEDULE_TAG.md.
Summary of work needed
-
_put / _async_put: Accept an extra_headers dict so conditional headers can
be injected.
-
save(if_schedule_tag_match=True): Currently accepted but silently ignored.
Wire it through to _put by reading self.props[cdav.ScheduleTag.tag], loading first
if the tag is not yet cached.
-
_reply_to_invite_request: Already fetches the schedule-tag property but never
uses it. Should call save(if_schedule_tag_match=True). The current fallback/recursive
logic also needs cleaning up.
-
Public schedule_tag property on CalendarObjectResource to avoid callers
importing cdav.
-
ScheduleTagMismatchError (subclass of PutError) for 412 responses so callers
can handle the re-fetch-and-merge case explicitly.
-
scheduling.schedule-tag compatibility hint — schedule-tag is a SHOULD in the
RFC, not all servers implement it.
Background
Schedule-Tag solves the attendee-update race condition: without If-Schedule-Tag-Match,
an attendee updating their PARTSTAT can silently overwrite an organizer update that
arrived between the attendee's GET and PUT. The tag is stable across PARTSTAT-only writes,
so it uniquely identifies the scheduling-significant version of the resource.
RFC refs: https://datatracker.ietf.org/doc/html/rfc6638#section-3.2 and section 3.3.
⚠️ This comment is AI-generated (Claude Sonnet 4.6 via Claude Code) on behalf of tobixen
The infrastructure for Schedule-Tag is half-built: the tag is received and cached, but
If-Schedule-Tag-Matchis never sent on PUT requests, leaving attendee PARTSTAT updatesunprotected against racing organizer updates.
Full analysis and suggested implementation steps are in
docs/design/TODO_SCHEDULE_TAG.md.Summary of work needed
_put/_async_put: Accept anextra_headersdict so conditional headers canbe injected.
save(if_schedule_tag_match=True): Currently accepted but silently ignored.Wire it through to
_putby readingself.props[cdav.ScheduleTag.tag], loading firstif the tag is not yet cached.
_reply_to_invite_request: Already fetches the schedule-tag property but neveruses it. Should call
save(if_schedule_tag_match=True). The current fallback/recursivelogic also needs cleaning up.
Public
schedule_tagproperty onCalendarObjectResourceto avoid callersimporting
cdav.ScheduleTagMismatchError(subclass ofPutError) for 412 responses so callerscan handle the re-fetch-and-merge case explicitly.
scheduling.schedule-tagcompatibility hint — schedule-tag is a SHOULD in theRFC, not all servers implement it.
Background
Schedule-Tag solves the attendee-update race condition: without
If-Schedule-Tag-Match,an attendee updating their PARTSTAT can silently overwrite an organizer update that
arrived between the attendee's GET and PUT. The tag is stable across PARTSTAT-only writes,
so it uniquely identifies the scheduling-significant version of the resource.
RFC refs: https://datatracker.ietf.org/doc/html/rfc6638#section-3.2 and section 3.3.