idnits 2.17.1 draft-ietf-jmap-calendars-06.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** There are 3 instances of too long lines in the document, the longest one being 11 characters in excess of 72. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (27 July 2021) is 1003 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) == Missing Reference: 'RFC XXX' is mentioned on line 297, but not defined Summary: 1 error (**), 0 flaws (~~), 2 warnings (==), 1 comment (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 JMAP N.M. Jenkins, Ed. 3 Internet-Draft Fastmail 4 Intended status: Standards Track M. Douglass, Ed. 5 Expires: 28 January 2022 Spherical Cow Group 6 27 July 2021 8 JMAP for Calendars 9 draft-ietf-jmap-calendars-06 11 Abstract 13 This document specifies a data model for synchronizing calendar data 14 with a server using JMAP. 16 Status of This Memo 18 This Internet-Draft is submitted in full conformance with the 19 provisions of BCP 78 and BCP 79. 21 Internet-Drafts are working documents of the Internet Engineering 22 Task Force (IETF). Note that other groups may also distribute 23 working documents as Internet-Drafts. The list of current Internet- 24 Drafts is at https://datatracker.ietf.org/drafts/current/. 26 Internet-Drafts are draft documents valid for a maximum of six months 27 and may be updated, replaced, or obsoleted by other documents at any 28 time. It is inappropriate to use Internet-Drafts as reference 29 material or to cite them other than as "work in progress." 31 This Internet-Draft will expire on 28 January 2022. 33 Copyright Notice 35 Copyright (c) 2021 IETF Trust and the persons identified as the 36 document authors. All rights reserved. 38 This document is subject to BCP 78 and the IETF Trust's Legal 39 Provisions Relating to IETF Documents (https://trustee.ietf.org/ 40 license-info) in effect on the date of publication of this document. 41 Please review these documents carefully, as they describe your rights 42 and restrictions with respect to this document. Code Components 43 extracted from this document must include Simplified BSD License text 44 as described in Section 4.e of the Trust Legal Provisions and are 45 provided without warranty as described in the Simplified BSD License. 47 Table of Contents 49 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 50 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4 51 1.2. The LocalDate Data Type . . . . . . . . . . . . . . . . . 4 52 1.3. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 53 1.4. Data Model Overview . . . . . . . . . . . . . . . . . . . 4 54 1.4.1. UIDs and CalendarEvent Ids . . . . . . . . . . . . . 5 55 1.5. Addition to the Capabilities Object . . . . . . . . . . . 6 56 1.5.1. urn:ietf:params:jmap:calendars . . . . . . . . . . . 6 57 1.5.2. urn:ietf:params:jmap:principals:availability . . . . 7 58 2. Principals and Sharing . . . . . . . . . . . . . . . . . . . 7 59 2.1. Principal Capability urn:ietf:params:jmap:calendars . . . 7 60 2.2. Principal/getAvailability . . . . . . . . . . . . . . . . 8 61 3. Participant Identities . . . . . . . . . . . . . . . . . . . 10 62 3.1. ParticipantIdentity/get . . . . . . . . . . . . . . . . . 11 63 3.2. ParticipantIdentity/changes . . . . . . . . . . . . . . . 11 64 3.3. ParticipantIdentity/set . . . . . . . . . . . . . . . . . 11 65 4. Calendars . . . . . . . . . . . . . . . . . . . . . . . . . . 11 66 4.1. Calendar/get . . . . . . . . . . . . . . . . . . . . . . 16 67 4.2. Calendar/changes . . . . . . . . . . . . . . . . . . . . 16 68 4.3. Calendar/set . . . . . . . . . . . . . . . . . . . . . . 16 69 5. Calendar Events . . . . . . . . . . . . . . . . . . . . . . . 17 70 5.1. Additional JSCalendar properties . . . . . . . . . . . . 19 71 5.1.1. mayInviteSelf . . . . . . . . . . . . . . . . . . . . 19 72 5.1.2. mayInviteOthers . . . . . . . . . . . . . . . . . . . 19 73 5.1.3. hideAttendees . . . . . . . . . . . . . . . . . . . . 19 74 5.2. Attachments . . . . . . . . . . . . . . . . . . . . . . . 19 75 5.3. Per-user properties . . . . . . . . . . . . . . . . . . . 19 76 5.4. Recurring events . . . . . . . . . . . . . . . . . . . . 20 77 5.5. Updating for "this-and-future" . . . . . . . . . . . . . 20 78 5.5.1. Splitting an event . . . . . . . . . . . . . . . . . 21 79 5.5.2. Updating the base event and overriding previous . . . 21 80 5.6. CalendarEvent/get . . . . . . . . . . . . . . . . . . . . 21 81 5.7. CalendarEvent/changes . . . . . . . . . . . . . . . . . . 23 82 5.8. CalendarEvent/set . . . . . . . . . . . . . . . . . . . . 23 83 5.8.1. Patching . . . . . . . . . . . . . . . . . . . . . . 25 84 5.8.2. Sending invitations and responses . . . . . . . . . . 28 85 5.9. CalendarEvent/copy . . . . . . . . . . . . . . . . . . . 31 86 5.10. CalendarEvent/query . . . . . . . . . . . . . . . . . . . 31 87 5.10.1. Filtering . . . . . . . . . . . . . . . . . . . . . 32 88 5.10.2. Sorting . . . . . . . . . . . . . . . . . . . . . . 33 89 5.11. CalendarEvent/queryChanges . . . . . . . . . . . . . . . 34 90 5.12. Examples . . . . . . . . . . . . . . . . . . . . . . . . 34 91 6. Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 92 6.1. Default alerts . . . . . . . . . . . . . . . . . . . . . 34 93 6.2. Acknowledging an alert . . . . . . . . . . . . . . . . . 35 94 6.3. Snoozing an alert . . . . . . . . . . . . . . . . . . . . 35 95 6.4. Push events . . . . . . . . . . . . . . . . . . . . . . . 35 96 7. Calendar Event Notifications . . . . . . . . . . . . . . . . 36 97 7.1. Auto-deletion of Notifications . . . . . . . . . . . . . 37 98 7.2. Object Properties . . . . . . . . . . . . . . . . . . . . 37 99 7.3. CalendarEventNotification/get . . . . . . . . . . . . . . 38 100 7.4. CalendarEventNotification/changes . . . . . . . . . . . . 38 101 7.5. CalendarEventNotification/set . . . . . . . . . . . . . . 38 102 7.6. CalendarEventNotification/query . . . . . . . . . . . . . 38 103 7.6.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 38 104 7.6.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 39 105 7.7. CalendarEventNotification/queryChanges . . . . . . . . . 39 106 8. Security Considerations . . . . . . . . . . . . . . . . . . . 39 107 8.1. Denial-of-service Expanding Recurrences . . . . . . . . . 39 108 8.2. Privacy . . . . . . . . . . . . . . . . . . . . . . . . . 39 109 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 39 110 9.1. JMAP Capability Registration for "calendars" . . . . . . 39 111 9.2. JSCalendar Property Registrations . . . . . . . . . . . . 40 112 9.2.1. id . . . . . . . . . . . . . . . . . . . . . . . . . 40 113 9.2.2. calendarIds . . . . . . . . . . . . . . . . . . . . . 40 114 9.2.3. isDraft . . . . . . . . . . . . . . . . . . . . . . . 40 115 9.2.4. utcStart . . . . . . . . . . . . . . . . . . . . . . 40 116 9.2.5. utcEnd . . . . . . . . . . . . . . . . . . . . . . . 41 117 9.2.6. mayInviteSelf . . . . . . . . . . . . . . . . . . . . 41 118 9.2.7. mayInviteOthers . . . . . . . . . . . . . . . . . . . 41 119 9.2.8. hideAttendees . . . . . . . . . . . . . . . . . . . . 41 120 10. Normative References . . . . . . . . . . . . . . . . . . . . 41 121 11. Informative References . . . . . . . . . . . . . . . . . . . 42 122 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 42 124 1. Introduction 126 JMAP ([RFC8620] - JSON Meta Application Protocol) is a generic 127 protocol for synchronizing data, such as mail, calendars or contacts, 128 between a client and a server. It is optimized for mobile and web 129 environments, and aims to provide a consistent interface to different 130 data types. 132 This specification defines a data model for synchronizing calendar 133 data between a client and a server using JMAP. The data model is 134 designed to allow a server to provide consistent access to the same 135 data via CalDAV [RFC4791] as well as JMAP, however the functionality 136 offered over the two protocols may differ. Unlike CalDAV, this 137 specification does not define access to tasks or journal entries 138 (VTODO or VJOURNAL iCalendar components in CalDAV). 140 1.1. Notational Conventions 142 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 143 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 144 "OPTIONAL" in this document are to be interpreted as described in BCP 145 14 [RFC2119] [RFC8174] when, and only when, they appear in all 146 capitals, as shown here. 148 Type signatures, examples, and property descriptions in this document 149 follow the conventions established in Section 1.1 of [RFC8620]. Data 150 types defined in the core specification are also used in this 151 document. 153 1.2. The LocalDate Data Type 155 Where "LocalDate" is given as a type, it means a string in the same 156 format as "Date" (see [RFC8620], Section 1.4), but with the "time- 157 offset" omitted from the end. The interpretation in absolute time 158 depends upon the time zone for the event, which may not be a fixed 159 offset (for example when daylight saving time occurs). For example, 160 "2014-10-30T14:12:00". 162 1.3. Terminology 164 The same terminology is used in this document as in the core JMAP 165 specification, see [RFC8620], Section 1.6. 167 The terms ParticipantIdentity, Calendar, CalendarEvent, and 168 CalendarEventNotification (with these specific capitalizations) are 169 used to refer to the data types defined in this document and 170 instances of those data types. 172 1.4. Data Model Overview 174 An Account (see [RFC8620], Section 1.6.2) with support for the 175 calendar data model contains zero or more Calendar objects, which is 176 a named collection of CalendarEvents. Calendars can also provide 177 defaults, such as alerts and a color to apply to events in the 178 calendar. Clients commonly let users toggle visibility of events 179 belonging to a particular calendar on/off. Servers may allow an 180 event to belong to multiple Calendars within an account. 182 A CalendarEvent is a representation of an event or recurring series 183 of events in JSEvent [I-D.ietf-calext-jscalendar] format. Simple 184 clients may ask the server to expand recurrences for them within a 185 specific time period, and optionally convert times into UTC so they 186 do not have to handle time zone conversion. More full-featured 187 clients will want to access the full event information and handle 188 recurrence expansion and time zone conversion locally. 190 CalendarEventNotification objects keep track of the history of 191 changes made to a calendar by other users, allowing calendar clients 192 to notify the user of changes to their schedule. 194 The ParticipantIdentity data type represents the identities of the 195 current user within an Account, which determines which events the 196 user is a participant of and possibly their permissions related to 197 that event. 199 In servers with support for JMAP Sharing [RFC XXX], data may be 200 shared with other users. Sharing permissions are managed per 201 calendar. For example, an individual may have separate calendars for 202 personal and work activities, with both contributing to their free- 203 busy availability, but only the work calendar shared in its entirety 204 with colleagues. Principals may also represent schedulable entities, 205 such as a meeting room. 207 Users can normally subscribe to any calendar to which they have 208 access. This indicates the user wants this calendar to appear in 209 their regular list of calendars. The separate "isVisible" property 210 stores whether the user would currently like to view the events in a 211 subscribed calendar. 213 1.4.1. UIDs and CalendarEvent Ids 215 Each CalendarEvent has a "uid" property 216 ([I-D.ietf-calext-jscalendar], Section 4.1.2), which is a globally 217 unique identifier that identifies the same event in different 218 Accounts, or different instances of the same recurring event within 219 an Account. 221 An Account MUST NOT contain more than one CalendarEvent with the same 222 uid unless all of the CalendarEvent objects have distinct, non-null 223 values for their "recurrenceId" property. (This situation occurs if 224 the principal is added to one or more specific instances of a 225 recurring event without being invited to the whole series.) 226 Each CalendarEvent also has an id, which is scoped to the JMAP 227 Account and used for referencing it in JMAP methods. There is no 228 necessary link between the uid property and the CalendarEvent's id. 229 CalendarEvents with the same uid in different Accounts MAY have 230 different ids. 232 1.5. Addition to the Capabilities Object 234 The capabilities object is returned as part of the JMAP Session 235 object; see [RFC8620], Section 2. This document defines two 236 additional capability URIs. 238 1.5.1. urn:ietf:params:jmap:calendars 240 This represents support for the Calendar, CalendarEvent, 241 CalendarEventNotification, and ParticipantIdentity data types and 242 associated API methods. The value of this property in the JMAP 243 Session capabilities property is an empty object. 245 The value of this property in an account's accountCapabilities 246 property is an object that MUST contain the following information on 247 server capabilities and permissions for that account: 249 * *shareesActAs*: "String" This MUST be one of: 251 - "self" - sharees act as themselves when using calendars in this 252 account. 254 - "secretary"- sharees act as the principal to which this account 255 belongs. 257 * *maxCalendarsPerEvent*: "UnsignedInt|null" The maximum number of 258 Calendars (see Section XXX) that can be can assigned to a single 259 CalendarEvent object (see Section XXX). This MUST be an integer 260 >= 1, or null for no limit (or rather, the limit is always the 261 number of Calendars in the account). 263 * *minDateTime*: "LocalDate" The earliest date-time the server is 264 willing to accept for any date stored in a CalendarEvent. 266 * *maxDateTime*: "LocalDate" The latest date-time the server is 267 willing to accept for any date stored in a CalendarEvent. 269 * *maxExpandedQueryDuration*: "Duration" The maximum duration the 270 user may query over when asking the server to expand recurrences. 272 * *maxParticipantsPerEvent*: "Number|null" The maximum number of 273 participants a single event may have, or null for no limit. 275 * *mayCreateCalendar*: "Boolean" If true, the user may create a 276 calendar in this account. 278 1.5.2. urn:ietf:params:jmap:principals:availability 280 Represents support for the Principal/getAvailability method. Any 281 account with this capability MUST also have the 282 "urn:ietf:params:jmap:principals" capability (see [RFC XXX]). 284 The value of this property in the JMAP Session capabilities property 285 is an empty object. 287 The value of this property in an account's accountCapabilities 288 property is an object that MUST contain the following information on 289 server capabilities and permissions for that account: 291 * *maxAvailabilityDuration*: The maximum duration over which the 292 server is prepared to calculate availability in a single call (see 293 Section XXX). 295 2. Principals and Sharing 297 For systems that also support JMAP Sharing [RFC XXX], the calendars 298 capability is used to indicate that this principal may be used with 299 calendaring. A new method is defined to allow users to query 300 availability when scehduling events. 302 2.1. Principal Capability urn:ietf:params:jmap:calendars 304 A "urn:ietf:params:jmap:calendars" property is added to the Principal 305 "capabilities" object, the value of which is an object with the 306 following properties: 308 * *accountId*: "Id|null" Id of Account with the 309 "urn:ietf:params:jmap:calendars" capability that contains the 310 calendar data for this principal, or null if none (e.g. the 311 Principal is a group just used for permissions management), or the 312 user does not have access to any data in the account (with the 313 exception of free/busy, which is governed by the 314 mayGetAvailability property). 316 * *account*: "Account|null" The JMAP Account object corresponding to 317 the accountId, null if none. 319 * *mayGetAvailability*: "Boolean" May the user call the "Principal/ 320 getAvailability" method with this Principal? 322 * *sendTo*: "String[String]|null" If this principal may be added as 323 a participant to an event, this is the map of methods for adding 324 it, in the same format as Participant#sendTo in JSEvent (see 325 [I-D.ietf-calext-jscalendar], Section 4.4.5). 327 2.2. Principal/getAvailability 329 This method calculates the availability of the principal for 330 scheduling within a requested time period. It takes the following 331 arguments: 333 * *accountId*: "Id" The id of the account to use. 335 * *id*: "Id" The id of the Principal to calculate availability for. 337 * *utcStart*: "UTCDate" The start time (inclusive) of the period for 338 which to return availability. 340 * *utcEnd*: "UTCDate" The end time (exclusive) of the period for 341 which to return availability. 343 * *showDetails*: "Boolean" If true, event details will be returned 344 if the user has permission to view them. 346 * *eventProperties*: "String[]|null" A list of properties to include 347 in any JSEvent object returned. If "null", all properties of the 348 event will be returned. Otherwise, only properties with names in 349 the given list will be returned. 351 The server will first find all relevant events, expanding any 352 recurring events. Relevant events are ones where all of the 353 following is true: 355 * The principal is subscribed to the calendar. 357 * Either the calendar belongs to the principal or the calendar 358 account's "shareesActAs" property is "self". 360 * The "includeInAvailability" property of the calendar for the 361 principal is "all" or "attending". 363 * The user has the "mayReadFreeBusy" permission for the calendar. 365 * The event finishes after the "utcStart" argument and starts before 366 the "utcEnd" argument. 368 * The event's "privacy" property is not "secret". 370 * The "freeBusyStatus" property of the event is "busy" (or omitted, 371 as this is the default). 373 * The "status" property of the event is not "cancelled". 375 * If the "includeInAvailability" property of the calendar is 376 "attending", then the principal is a participant of the event, and 377 has a "participationStatus" of "accepted" or "tentative". 379 If an event is in more than one calendar, it is relevant if all of 380 the above are true for any one calendar that it is in. 382 The server then generates a BusyPeriod object for each of these 383 events. A *BusyPeriod* object has the following properties: 385 * *utcStart*: "UTCDate" The start time (inclusive) of the period 386 this represents. 388 * *utcEnd*: "UTCDate" The end time (exclusive) of the period this 389 represents. 391 * *busyStatus*: "String" (optional, default "unavailable") This MUST 392 be one of 394 - "confirmed": The event status is "confirmed". 396 - "tentative": The event status is "tentative". 398 - "unavailable": The principal is not available for scheduling at 399 this time for any other reason. 401 * *event*: "JSEvent|null" The JSEvent representation of the event, 402 or null if any of the following are true: 404 - The "showDetails" argument is false. 406 - The "privacy" property of the event is "private". 408 - The user does not have the "mayReadItems" permission for any of 409 the calendars the event is in. 411 If an eventProperties argument was given, any properties in the 412 JSEvent that are not in the eventProperties list are removed from 413 the returned representation. 415 The server MAY also generate BusyPeriod objects based on other 416 information it has about the principal's availability, such as office 417 hours. 419 Finally, the server MUST merge and split BusyPeriod objects where the 420 "event" property is null, such that none of them overlap and either 421 there is a gap in time between any two objects (the utcEnd of one 422 does not equal the utcStart of another) or those objects have a 423 different busyStatus property. If there are overlapping BusyPeriod 424 time ranges with different "busyStatus" properties the server MUST 425 choose the value in the following order: confirmed > unavailable > 426 tentative. 428 The response has the following argument: 430 * *list*: "BusyPeriod[]" The list of BusyPeriod objects calculated 431 as described above. 433 The following additional errors may be returned instead of the 434 "Principal/getAvailability" response: 436 "notFound": No principal with this id exists, or the user does not 437 have permission to see that this principal exists. 439 "forbidden": The user does not have permission to query this 440 principal's availability. 442 "tooLarge": The duration between utcStart an utcEnd is longer than 443 the server is willing to calculate availability for. 445 "rateLimit": Too many availability requests have been made recently 446 and the user is being rate limited. It may work to try again later. 448 3. Participant Identities 450 A ParticipantIdentity stores information about a URI that represents 451 the user within that account in an event's participants. It has the 452 following properties: 454 * *id*: "Id" (immutable; server-set) The id of the 455 ParticipantIdentity. 457 * *name*: "String" (default: "") The display name of the participant 458 to use when adding this participant to an event, e.g. "Joe 459 Bloggs". 461 * *sendTo*: "String[String]" Represents methods by which the 462 participant may receive invitations and updates to an event. 464 The keys in the property value are the available methods and MUST 465 only contain ASCII alphanumeric characters (A-Za-z0-9). The value 466 is a URI for the method specified in the key. 468 A participant in an event corresponds to a ParticipantIdentity if any 469 of the method/uri pairs in the sendTo property of the participant are 470 identical to a method/uri pair in the sendTo property of the 471 identity. 473 The following JMAP methods are supported. 475 3.1. ParticipantIdentity/get 477 This is a standard "/get" method as described in [RFC8620], 478 Section 5.1. The _ids_ argument may be "null" to fetch all at once. 480 3.2. ParticipantIdentity/changes 482 This is a standard "/changes" method as described in [RFC8620], 483 Section 5.2. 485 3.3. ParticipantIdentity/set 487 This is a standard "/set" method as described in [RFC8620], 488 Section 5.3. The server MAY restrict the uri values the user may 489 claim, for example only allowing "mailto:" URIs with email addresses 490 that belong to the user. A standard "forbidden" error is returned to 491 reject non-permissible changes. 493 4. Calendars 495 A Calendar is a named collection of events. All events are 496 associated with at least one calendar. 498 A *Calendar* object has the following properties: 500 * *id*: "Id" (immutable; server-set) The id of the calendar. 502 * *role*: "String|null" (default: null) Denotes the calendar has a 503 special purpose. This MUST be one of the following: 505 - "inbox": This is the principal's default calendar; when the 506 principal is invited to an event, this is the calendar to which 507 it will be added by the server. There MUST NOT be more than 508 one calendar with this role in an account. 510 - "templates": This calendar holds templates for creating new 511 events. All events in this calendar MUST have the "isDraft" 512 property set to true. Clients should not show this as a 513 regular calendar to users, but may offer users to create new 514 events by copying one of the events in here. 516 * *name*: "String" The user-visible name of the calendar. This may 517 be any UTF-8 string of at least 1 character in length and maximum 518 255 octets in size. 520 * *description*: "String|null" (default: null) An optional longer- 521 form description of the calendar, to provide context in shared 522 environments where users need more than just the name. 524 * *color*: "String|null" (default: null) A color to be used when 525 displaying events associated with the calendar. 527 If not null, the value MUST be a case-insensitive color name taken 528 from the set of names defined in Section 4.3 of CSS Color Module 529 Level 3 COLORS (https://www.w3.org/TR/css-color-3/), or an RGB value 530 in hexadecimal notation, as defined in Section 4.2.1 of CSS Color 531 Module Level 3. 533 The color SHOULD have sufficient contrast to be used as text on a white background. 535 * *sortOrder*: "UnsignedInt" (default: 0) Defines the sort order of 536 calendars when presented in the client's UI, so it is consistent 537 between devices. The number MUST be an integer in the range 0 <= 538 sortOrder < 2^(31.) 540 A calendar with a lower order should be displayed before a 541 calendar with a higher order in any list of calendars in the 542 client's UI. Calendars with equal order SHOULD be sorted in 543 alphabetical order by name. The sorting should take into account 544 locale-specific character order convention. 546 * *isSubscribed*: "Boolean" Has the user indicated they wish to see 547 this Calendar in their client? This SHOULD default to false for 548 Calendars in shared accounts the user has access to and true for 549 any new Calendars created by the user themself. 551 If false, the calendar should only be displayed when the user 552 explicitly requests it or to offer it for the user to subscribe 553 to. 555 * *isVisible*: "Boolean" (default: true) Should the calendar's 556 events be displayed to the user at the moment? Clients MUST 557 ignore this property if isSubscribed is false. If an event is in 558 multiple calendars, it should be displayed if isVisible is true 559 for any of those calendars. 561 * *includeInAvailability*: "String" (default: all) Should the 562 calendar's events be used as part of availability calculation? 563 This MUST be one of: 565 - "all": all events are considered. 567 - "attending": events the user is a confirmed or tentative 568 participant of are considered. 570 - "none": all events are ignored (but may be considered if also 571 in another calendar). 573 * *defaultAlertsWithTime*: "Id[Alert]|null" (default: null) A map of 574 alert ids to Alert objects (see [I-D.ietf-calext-jscalendar], 575 Section 4.5.2) to apply for events where "showWithoutTime" is 576 false and "useDefaultAlerts" is true. Ids MUST be unique across 577 all default alerts in the account, including those in other 578 calendars; a UUID is recommended. 580 * *defaultAlertsWithoutTime*: "Id[Alert]|null" (default: null) A map 581 of alert ids to Alert objects (see [I-D.ietf-calext-jscalendar], 582 Section 4.5.2) to apply for events where "showWithoutTime" is true 583 and "useDefaultAlerts" is true. Ids MUST be unique across all 584 default alerts in the account, including those in other calendars; 585 a UUID is recommended. 587 * *timeZone*: "String|null" (default: null) The time zone to use for 588 events without a time zone when the server needs to resolve them 589 into absolute time, e.g., for alerts or availability calculation. 590 The value MUST be a time zone id from the IANA Time Zone Database 591 TZDB (https://www.iana.org/time-zones). If "null", the timeZone 592 of the account's associated Principal will be used. Clients 593 SHOULD use this as the default for new events in this calendar if 594 set. 596 * *shareWith*: "Id[CalendarRights]|null" (default: null) A map of 597 Principal id to rights for principals this calendar is shared 598 with. The principal to which this calendar belongs MUST NOT be in 599 this set. This is null if the user requesting the object does not 600 have the mayAdmin right, or if the calendar is not shared with 601 anyone. May be modified only if the user has the mayAdmin right. 602 The account id for the principals may be found in the 603 "urn:ietf:params:jmap:principals:owner" capability of the Account 604 to which the calendar belongs. 606 * *myRights*: "CalendarRights" (server-set) The set of access rights 607 the user has in relation to this Calendar. If any event is in 608 multiple calendars, the user has the following rights: 610 - The user may fetch the event if they have the mayReadItems 611 right on any calendar the event is in. 613 - The user may remove an event from a calendar (by modifying the 614 event's "calendarIds" property) if the user has the appropriate 615 permission for that calendar. 617 - The user may make other changes to the event if they have the 618 right to do so in _all_ calendars to which the event belongs. 620 A *CalendarRights* object has the following properties: 622 * *mayReadFreeBusy*: "Boolean" The user may read the free-busy 623 information for this calendar as part of a call to Principal/ 624 getAvailability (see Section XXX). 626 * *mayReadItems*: "Boolean" The user may fetch the events in this 627 calendar. 629 * *mayAddItems*: "Boolean" The user may create new events on this 630 calendar or move events to this calendar. For recurring events, 631 they may add an override to add an occurrence, or remove an 632 existing override that is excluding an occurrence. 634 * *mayUpdatePrivate*: "Boolean" The user may modify the following 635 properties on all events in the calendar. If the shareesActAs 636 account capability is "self", these properties MUST all be stored 637 per-user, and changes do not affect any other user of the 638 calendar. If shareesActAs is "secretary", the values are shared 639 between all users. 641 - keywords 643 - color 645 - freeBusyStatus 647 - useDefaultAlerts 649 - alerts 651 The user may also modify the above on a per-occurrence basis for 652 recurring events. 654 * *mayRSVP*: "Boolean" The user may modify the 655 "participationStatus", "participationComment", "expectReply", 656 "scheduleAgent", "scheduleSequence", and "scheduleUpdated" 657 properties of any Participant object that corresponds to one of 658 the user's ParticipantIdentity objects in the account. 660 If the event has its "mayInviteSelf" property set to true (see 661 Section XXX), then the user may also add a new Participant to the 662 event with a sendTo property that is the same as the sendTo 663 property of one of the user's ParticipantIdentity objects in the 664 account. The roles property of the participant MUST only contain 665 "attendee". 667 If the event has its "mayInviteOthers" property set to true (see 668 Section XXX) and there is an existing Participant in the event 669 corresponding to one of the user's ParticipantIdentity objects in 670 the account, then the user may also add new participants. The 671 roles property of any new participant MUST only contain 672 "attendee". 674 The user may also do all of the above on a per-occurrence basis 675 for recurring events. 677 * *mayUpdateOwn*: "Boolean" The user may modify an existing event on 678 this calendar if either they are the owner of the event or the 679 event has no owner. 681 * *mayUpdateAll*: "Boolean" The user may modify all existing events 682 on this calendar. 684 * *mayRemoveOwn*: "Boolean" The user may delete an event or remove 685 it from this calendar if either they are the owner of the event or 686 the event has no owner. For recurring events, they may add an 687 override to remove an occurrence. 689 * *mayRemoveAll*: "Boolean" The user may delete any event or remove 690 it from this calendar. For recurring events, they may add an 691 override to remove an occurrence. 693 * *mayAdmin*: "Boolean" The user may modify sharing for this 694 calendar. 696 * *mayDelete*: "Boolean" (server-set) The user may delete the 697 calendar itself. This property MUST be false if the account to 698 which this calendar belongs has the _isReadOnly_ property set to 699 true. 701 The user is an *owner* for an event if the CalendarEvent object has a 702 "participants" property, and one of the Participant objects both: 704 a) Has the "owner" role. 705 b) Corresponds to one of the user's ParticipantIdentity objects in the account. 707 An event has no owner if its participants property is null or 708 omitted, or if none of the Participant objects have the "owner" role. 710 4.1. Calendar/get 712 This is a standard "/get" method as described in [RFC8620], 713 Section 5.1. The _ids_ argument may be "null" to fetch all at once. 715 If mayReadFreeBusy is the only permission the user has, the calendar 716 MUST NOT be returned in Calendar/get and Calendar/query; it must 717 behave as though it did not exist. The data is just used as part of 718 Principal/getAvailability. 720 4.2. Calendar/changes 722 This is a standard "/changes" method as described in [RFC8620], 723 Section 5.2. 725 4.3. Calendar/set 727 This is a standard "/set" method as described in [RFC8620], 728 Section 5.3 but with the following additional request argument: 730 * *onDestroyRemoveEvents*: "Boolean" (default: false) 732 If false, any attempt to destroy a Calendar that still has 733 CalendarEvents in it will be rejected with a "calendarHasEvent" 734 SetError. If true, any CalendarEvents that were in the Calendar will 735 be removed from it, and if in no other Calendars they will be 736 destroyed. This SHOULD NOT send scheduling messages to participants 737 or create CalendarEventNotification objects. 739 The "role" and "shareWith" properties may only be set by users that 740 have the mayAdmin right. The value is shared across all users, 741 although users without the mayAdmin right cannot see the value. 743 When modifying the shareWith property, the user cannot give a right 744 to a principal if the principal did not already have that right and 745 the user making the change also does not have that right. Any 746 attempt to do so must be rejected with a "forbidden" SetError. 748 Users can subscribe or unsubscribe to a calendar by setting the 749 "isSubscribed" property. The server MAY forbid users from 750 subscribing to certain calendars even though they have permission to 751 see them, rejecting the update with a "forbidden" SetError. 753 The "timeZone", "includeInAvailability", "defaultAlertsWithoutTime" 754 and "defaultAlertsWithTime" properties are stored per-user if the 755 calendar account's "shareesActAs" capability is "self", and may be 756 set by any user who is subscribed to the calendar. Otherwise, these 757 properties are shared, and may only be set by users that have the 758 mayAdmin right. 760 The following properties may be set by anyone who is subscribed to 761 the calendar and are all stored per-user: 763 * name 765 * color 767 * sortOrder 769 * isVisible 771 These properties are initially inherited from the owner's copy of the 772 calendar, but if set by a sharee that user gets their own copy of the 773 property; it does not change for any other principals. If the value 774 of the property in the owner's calendar changes after this, it does 775 not overwrite the sharee's value. 777 The following extra SetError types are defined: 779 For "destroy": 781 * *calendarHasEvent*: The Calendar has at least one CalendarEvent 782 assigned to it, and the "onDestroyRemoveEvents" argument was 783 false. 785 5. Calendar Events 787 A *CalendarEvent* object contains information about an event, or 788 recurring series of events, that takes place at a particular time. 789 It is a JSEvent object, as defined in [I-D.ietf-calext-jscalendar], 790 with the following additional properties: 792 * *id*: "Id" The id of the CalendarEvent. This property is 793 immutable. The id uniquely identifies a JSEvent with a particular 794 "uid" and "recurrenceId" within a particular account. 796 * *calendarIds*: "Id[Boolean]" The set of Calendar ids this event 797 belongs to. An event MUST belong to one or more Calendars at all 798 times (until it is destroyed). The set is represented as an 799 object, with each key being a _Calendar id_. The value for each 800 key in the object MUST be "true". 802 * *isDraft*: "Boolean" If true, this event is to be considered a 803 draft. The server will not send any scheduling messages to 804 participants or send push notifications for alerts. This may only 805 be set to true upon creation. Once set to false, the value cannot 806 be updated to true. This property MUST NOT appear in 807 "recurrenceOverrides". 809 * *utcStart*: "UTCDate" For simple clients that do not or cannot 810 implement time zone support. Clients should only use this if also 811 asking the server to expand recurrences, as you cannot accurately 812 expand a recurrence without the original time zone. 814 This property is calculated at fetch time by the server. Time 815 zones are political and they can and do change at any time. 816 Fetching exactly the same property again may return a different 817 results if the time zone data has been updated on the server. 818 Time zone data changes are not considered "updates" to the event. 820 If set, server will convert to the event's current time zone using 821 its current time zone data and store the local time. 823 This is not included by default and must be requested explicitly. 825 Floating events (events without a time zone) will be interpreted 826 as per the time zone given as a CalendarEvent/get argument. 828 Note that it is not possible to accurately calculate the expansion 829 of recurrence rules or recurrence overrides with the utcStart 830 property rather than the local start time. Even simple 831 recurrences such as "repeat weekly" may cross a daylight-savings 832 boundary and end up at a different UTC time. Clients that wish to 833 use "utcStart" are RECOMMENDED to request the server expand 834 recurrences (see Section XXX). 836 * *utcEnd*: "UTCDate" The server calculates the end time in UTC from 837 the start/timeZone/duration properties of the event. This is not 838 included by default and must be requested explicitly. Like 839 utcStart, this is calculated at fetch time if requested and may 840 change due to time zone data changes. Floating events will be 841 interpreted as per the time zone given as a CalendarEvent/get 842 argument. 844 CalendarEvent objects MUST NOT have a "method" property as this is 845 only used when representing iTIP [RFC5546] scheduling messages, not 846 events in a data store. 848 5.1. Additional JSCalendar properties 850 This document defines three new JSCalendar properties. 852 5.1.1. mayInviteSelf 854 Type: "Boolean" (default: false) 856 If "true", any user that has access to the event may add themselves 857 to it as a participant with the "attendee" role. This property MUST 858 NOT be altered in the recurrenceOverrides; it may only be set on the 859 base object. 861 5.1.2. mayInviteOthers 863 Type: "Boolean" (default: false) 865 If "true", any current participant with the "attendee" role may add 866 new participants with the "attendee" role to the event. This 867 property MUST NOT be altered in the recurrenceOverrides; it may only 868 be set on the base object. 870 5.1.3. hideAttendees 872 Type: "Boolean" (default: false) 874 If "true", only the owners of the event may see the full set of 875 participants. Other sharees of the event may only see the owners and 876 themselves. This property MUST NOT be altered in the 877 recurrenceOverrides; it may only be set on the base object. 879 5.2. Attachments 881 The Link object, as defined in [I-D.ietf-calext-jscalendar] 882 Section 4.2.7, with a "rel" property equal to "enclosure" is used to 883 represent attachments. Instead of mandating an "href" property, 884 clients may set a "blobId" property instead to reference a blob of 885 binary data in the account, as per [RFC8620] Section 6. 887 The server MUST translate this to an embedded "data:" URL [RFC2397] 888 when sending the event to a system that cannot access the blob. 889 Servers that support CalDAV access to the same data are recommended 890 to expose these files as managed attachments [?@RFC8607]. 892 5.3. Per-user properties 894 In shared calendars where the account's "shareesActAs" capability is 895 "self", the following properties MUST be stored per-user: 897 * keywords 899 * color 901 * freeBusyStatus 903 * useDefaultAlerts 905 * alerts 907 The user may also modify these properties on a per-occurrence basis 908 for recurring events; again, these MUST be stored per-user. 910 When writing only per-user properties, the "updated" property MUST 911 also be stored just for that user. When fetching the "updated" 912 property, the value to return is whichever is later of the per-user 913 updated time or the updated time of the base event. 915 5.4. Recurring events 917 Events may recur, in which case they represent multiple occurrences 918 or instances. The data store will either contain a single base 919 event, containing a recurrence rule and/or recurrence overrides; or, 920 a set of individual instances (when invited to specific occurrences 921 only). 923 The client may ask the server to expand recurrences within a specific 924 time range in "CalendarEvent/query". This will generate synthetic 925 ids representing individual instances in the requested time range. 926 The client can fetch and update the objects using these ids and the 927 server will make the appropriate changes to the base event. 928 Synthetic ids do not appear in "CalendarEvent/changes" responses; 929 only the ids of events as actually stored on the server. 931 If the user is invited to specific instances then later added to the 932 base event, "CalendarEvent/changes" will show the ids of all the 933 individual instances being destroyed and the id for the base event 934 being created. 936 5.5. Updating for "this-and-future" 938 When editing a recurring event, you can either update the base event 939 (affecting all instances unless overriden) or update an override for 940 a specific occurrence. To update all occurrences from a specific 941 point onwards, there are therefore two options: split the event, or 942 update the base event and override all occurrences before the split 943 point back to their original values. 945 5.5.1. Splitting an event 947 If the event is not scheduled (has no participants), the simplest 948 thing to do is to duplicate the event, modifying the recurrence rules 949 of the original so it finishes before the split point, and the 950 duplicate so it starts at the split point. As per JSCalendar 951 [I-D.ietf-calext-jscalendar] Section 4.1.3, a "next" and "first" 952 relation MUST be set on the new objects respectively. 954 Splitting an event however is problematic in the case of a scheduled 955 event, because the iTIP messages generated make it appear like two 956 unrelated changes, which can be confusing. 958 5.5.2. Updating the base event and overriding previous 960 For scheduled events, a better approach is to avoid splitting and 961 instead update the base event with the new property value for "this 962 and future", then create overrides for all occurrences before the 963 split point to restore the property to its previous value. Indeed, 964 this may be the only option the user has permission to do if not an 965 owner of the event. 967 Clients may choose to skip creating the overrides if the old data is 968 not important, for example if the "alerts" property is being updated, 969 it is probably not important to create overrides for events in the 970 past with the alerts that have already fired. 972 5.6. CalendarEvent/get 974 This is a standard "/get" method as described in [RFC8620], 975 Section 5.1, with three extra arguments: 977 * *recurrenceOverridesBefore*: "UTCDate|null" If given, only 978 recurrence overrides with a recurrence id before this date (when 979 translated into UTC) will be returned. 981 * *recurrenceOverridesAfter*: "UTCDate|null" If given, only 982 recurrence overrides with a recurrence id on or after this date 983 (when translated into UTC) will be returned. 985 * *reduceParticipants*: "Boolean" (default: false) If true, only 986 participants with the "owner" role or corresponding to the user's 987 participant identities will be returned in the "participants" 988 property of the base event and any recurrence overrides. If 989 false, all participants will be returned. 991 * *timeZone*: "String" (default "Etc/UTC") The time zone to use when 992 calculating the utcStart/utcEnd property of floating events. This 993 argument has no effect if those properties are not requested. 995 A CalendarEvent object is a JSEvent object so may have arbitrary 996 properties. If the client makes a "CalendarEvent/get" call with a 997 null or omitted "properties" argument, all properties defined on the 998 JSEvent object in the store are returned, along with the "id", 999 "calendarIds", and "isDraft" properties. The "utcStart" and "utcEnd" 1000 computed properties are only returned if explicitly requested. If 1001 either are requested, the "recurrenceOverrides" property MUST NOT be 1002 requested (recurrence overrides cannot be interpreted accurately with 1003 just the UTC times). 1005 If specific properties are requested from the JSEvent and the 1006 property is not present on the object in the server's store, the 1007 server SHOULD return the default value if known for that property. 1009 A requested id may represent a single instance of a recurring event 1010 if the client asked the server to expand recurrences in 1011 "CalendarEvent/query". In such a case, the server will resolve any 1012 overrides and set the appropriate "start" and "recurrenceId" 1013 properties on the CalendarEvent object returned to the client. The 1014 "recurrenceRule" and "recurrenceOverrides" properties MUST be 1015 returned as null if requested for such an event. 1017 An event with the same uid/recurrenceId may appear in different 1018 accounts. Clients may coalesce the view of such events, but must be 1019 aware that the data may be different in the different accounts due to 1020 per-user properties, difference in permissions etc. 1022 The "privacy" property of a JSEvent object allows the owner to 1023 override how sharees of the calendar see the event. If this is set 1024 to "private", when a sharee fetches the event the server MUST only 1025 return the basic time and metadata properties of the JSEvent object 1026 as specified in [I-D.ietf-calext-jscalendar], Section 4.4.3. If set 1027 to "secret", the server MUST behave as though the event does not 1028 exist for all users other than the owner. 1030 This "hideAttendees" property of a JSEvent object allows the owner to 1031 reduce the visibility of sharees into the set of participants. If 1032 this is "true", when a non-owner sharee fetches the event, the server 1033 MUST only return participants with the "owner" role or corresponding 1034 to the user's participant identities. 1036 5.7. CalendarEvent/changes 1038 This is a standard "/changes" method as described in [RFC8620], 1039 Section 5.2. 1041 5.8. CalendarEvent/set 1043 This is a standard "/set" method as described in [RFC8620], 1044 Section 5.3, with the following extra argument: 1046 * *sendSchedulingMessages*: "Boolean" (default: false) If true then 1047 any changes to scheduled events will be sent to all the 1048 participants (if the user is an owner of the event) or back to the 1049 owners (otherwise). If false, the changes only affect this 1050 account and no scheduling messages will be sent. 1052 For recurring events, an id may represent the base event or a 1053 specific instance. When the id for a specific instance is given, the 1054 server MUST process an update as an update to the recurrence override 1055 for that instance on the base event, and a destroy as removing just 1056 that instance. 1058 Clients MUST NOT send an update/destroy to both the base event and a 1059 specific instance in a single "/set" request; the result of this is 1060 undefined. 1062 Servers MUST enforce the user's permissions as returned in the 1063 "myRights" property of the Calendar objects and reject changes with a 1064 "forbidden" SetError if not allowed. 1066 The "privacy" property MUST NOT be set to anything other than 1067 "public" (the default) for events in a calendar that does not belong 1068 to the user (e.g. a shared team calendar). The server MUST reject 1069 this with an "invalidProperties" SetError. 1071 The server MUST reject attempts to add events with a "participants" 1072 property where none of the participants correspond to one of the 1073 calendar's participant identities with a "forbidden" SetError. 1075 If omitted on create, the server MUST set the following properties to 1076 an appropriate value: 1078 * @type 1080 * uid 1082 * created 1083 The "updated" property MUST be set to the current time by the server 1084 whenever an event is created or updated. If the client tries to set 1085 a value for this property it is not an error, but it MUST be 1086 overridden and replaced with the server's time. 1088 When updating an event, if all of: * a non per-user property has been 1089 changed; and * the server is the source of the event (see 1090 Section XXX); and * the "sequence" property is not explicitly set in 1091 the update, or the given value is less than or equal to the current 1092 "sequence" value on the server; then the server MUST increment the 1093 "sequence" value by one. 1095 The "created" property MUST NOT be updated after creation. The 1096 "method" property MUST NOT be set. Any attempt to do these is 1097 rejected with a standard "invalidProperties" SetError. 1099 If "utcStart" is set, this is translated into a "start" property 1100 using the server's current time zone information. It MUST NOT be set 1101 in addition to a "start" property and it cannot be set inside 1102 "recurrenceOverrides"; this MUST be rejected with an 1103 "invalidProperties" SetError. 1105 Similarly, the "utcEnd" property is translated into a "duration" 1106 property if set. It MUST NOT be set in addition to a "duration" 1107 property and it cannot be set inside "recurrenceOverrides"; this MUST 1108 be rejected with an "invalidProperties" SetError. 1110 The server does not automatically reset the "partipationStatus" or 1111 "expectReply" properties of a Participant when changing other event 1112 details. Clients should either be intelligent about whether the 1113 change necessitates resending RSVP requests, or ask the user whether 1114 to send them. 1116 The server MAY enforce that all events have an owner, for example in 1117 team calendars. If the user tries to create an event without 1118 participants in such a calendar, the server MUST automatically add a 1119 participant with the "owner" role corresponding to one of the user's 1120 ParticipantIdentities (see Section XXX). 1122 When creating an event with participants, or adding participants to 1123 an event that previously did not have participants, the server MUST 1124 set the "replyTo" property of the event if not present. Clients 1125 SHOULD NOT set the replyTo property for events when the user adds 1126 participants; the server is better positioned to add all the methods 1127 it supports to receive replies. 1129 5.8.1. Patching 1131 The JMAP "/set" method allows you to update an object by sending a 1132 patch, rather than having to supply the whole object. When doing so, 1133 care must be taken if updating a property of a CalendarEvent where 1134 the value is itself a PatchObject, e.g. inside "localizations" or 1135 "recurrenceOverrides". In particular, you cannot add a property with 1136 value "null" to the CalendarEvent using a direct patch on that 1137 property, as this is interpreted instead as a patch to remove the 1138 property. This is more easily understood with an example. Suppose 1139 you have a CalendarEvent object like so: 1141 { 1142 "id": "123", 1143 "title": "FooBar team meeting", 1144 "start": "2018-01-08T09:00:00", 1145 "recurrenceRules": [{ 1146 "@type": "RecurrenceRule", 1147 "frequency": "weekly" 1148 }], 1149 "replyTo": { 1150 "imip": "mailto:6489-4f14-a57f-c1@schedule.example.com" 1151 }, 1152 "participants": { 1153 "dG9tQGZvb2Jhci5xlLmNvbQ": { 1154 "@type": "Participant", 1155 "name": "Tom", 1156 "email": "tom@foobar.example.com", 1157 "sendTo": { 1158 "imip": "mailto:6489-4f14-a57f-c1@calendar.example.com" 1159 }, 1160 "participationStatus": "accepted", 1161 "roles": { 1162 "attendee": true 1163 } 1164 }, 1165 "em9lQGZvb2GFtcGxlLmNvbQ": { 1166 "@type": "Participant", 1167 "name": "Zoe", 1168 "email": "zoe@foobar.example.com", 1169 "sendTo": { 1170 "imip": "mailto:zoe@foobar.example.com" 1171 }, 1172 "participationStatus": "accepted", 1173 "roles": { 1174 "owner": true, 1175 "attendee": true, 1176 "chair": true 1177 } 1178 }, 1179 "recurrenceOverrides": { 1180 "2018-03-08T09:00:00": { 1181 "start": "2018-03-08T10:00:00", 1182 "participants/dG9tQGZvb2Jhci5xlLmNvbQ/participationStatus": 1183 "declined" 1184 } 1185 } 1186 } 1187 } 1188 In this example, Tom is normally going to the weekly meeting but has 1189 declined the occurrence on 2018-03-08, which starts an hour later 1190 than normal. Now, if Zoe too were to decline that meeting, she could 1191 update the event by just sending a patch like so: 1193 [[ "CalendarEvent/set", { 1194 "accountId": "ue150411c", 1195 "update": { 1196 "123": { 1197 "recurrenceOverrides/2018-03-08T09:00:00/ 1198 participants~1em9lQGZvb2GFtcGxlLmNvbQ~1participationStatus": 1199 "declined" 1200 } 1201 } 1202 }, "0" ]] 1204 This patches the "2018-03-08T09:00:00" PatchObject in 1205 recurrenceOverrides so that it ends up like this: 1207 "recurrenceOverrides": { 1208 "2018-03-08T09:00:00": { 1209 "start": "2018-03-08T10:00:00", 1210 "participants/dG9tQGZvb2Jhci5xlLmNvbQ/participationStatus": 1211 "declined", 1212 "participants/em9lQGZvb2GFtcGxlLmNvbQ/participationStatus": 1213 "declined" 1214 } 1215 } 1217 Now if Tom were to change his mind and remove his declined status 1218 override (thus meaning he is attending, as inherited from the top- 1219 level event), he might remove his patch from the overrides like so: 1221 [[ "CalendarEvent/set", { 1222 "accountId": "ue150411c", 1223 "update": { 1224 "123": { 1225 "recurrenceOverrides/2018-03-08T09:00:00/ 1226 participants~1dG9tQGZvb2Jhci5xlLmNvbQ~1participationStatus": null 1227 } 1228 } 1229 }, "0" ]] 1231 However, if you instead want to remove Tom from this instance 1232 altogether, you could not send this patch: 1234 [[ "CalendarEvent/set", { 1235 "accountId": "ue150411c", 1236 "update": { 1237 "123": { 1238 "recurrenceOverrides/2018-03-08T09:00:00/ 1239 participants~1dG9tQGZvb2Jhci5xlLmNvbQ": null 1240 } 1241 } 1242 }, "0" ]] 1244 This would mean remove the "participants/dG9tQGZvb2Jhci5xlLmNvbQ" 1245 property at path "recurrenceOverrides" -> "2018-03-08T09:00:00" 1246 inside the object; but this doesn't exist. We actually we want to 1247 add this property and make it map to "null". The client must instead 1248 send the full object that contains the property mapping to "null", 1249 like so: 1251 [[ "CalendarEvent/set", { 1252 "accountId": "ue150411c", 1253 "update": { 1254 "123": { 1255 "recurrenceOverrides/2018-03-08T09:00:00": { 1256 "start": "2018-03-08T10:00:00", 1257 "participants/em9lQGZvb2GFtcGxlLmNvbQ/participationStatus": 1258 "declined" 1259 "participants/dG9tQGZvb2Jhci5xlLmNvbQ": null 1260 } 1261 } 1262 } 1263 }, "0" ]] 1265 5.8.2. Sending invitations and responses 1267 If "sendSchedulingMessages" is true, the server MUST send appropriate 1268 iTIP [RFC5546] scheduling messages after successfuly creating, 1269 updating or destroying a calendar event. 1271 When determining which scheduling messages to send, the server must 1272 first establish whether it is the _source_ of the event. The server 1273 is the source if it will receive messages sent to any of the methods 1274 specified in the "replyTo" property of the event. 1276 Messages are only sent to participants with a "scheduleAgent" 1277 property set to "server" or omitted. If the effective 1278 "scheduleAgent" property is changed: 1280 * to "server" from something else: send messages to this participant 1281 as though the event had just been created. 1283 * from "server" to something else: send messages to this participant 1284 as though the event had just been destroyed. 1286 * any other change: do not send any messages to this participant. 1288 The server may send the scheduling message via any of the methods 1289 defined on the sendTo property of a participant (if the server is the 1290 source) or the replyTo property of the event (otherwise) that it 1291 supports. If no supported methods are available, the server MUST 1292 reject the change with a "noSupportedScheduleMethods" SetError. 1294 If the server is the source of the event it MUST NOT send messages to 1295 any participant corresponding to a ParticipantIdentitity in that 1296 account (see Section XXX). 1298 If sending via iMIP [RFC6047], the server MAY choose to only send 1299 updates it deems "essential" to avoid flooding the recipient's email 1300 with changes they do not care about. For example, changes to the 1301 participationStatus of another participant, or changes to events 1302 solely in the past may be omitted. 1304 5.8.2.1. REQUEST 1306 When the server is the source for the event, a REQUEST message 1307 ([RFC5546], Section 3.2.2) is sent to all current participants if 1308 either: 1310 * The event is being created; or 1312 * Any non per-user property (see Section XXX) is updated on the 1313 event (including adding/removing participants), except if just 1314 modifying the recurrenceOverrides such that CANCEL messages are 1315 generated (see the next section). 1317 Note, if the only change is adding an additional instance (not 1318 generated by the event's recurrence rule) to the recurrenceOverrides, 1319 this MAY be handled via sending an ADD message ([RFC5546], 1320 Section 3.2.4) for the single instance rather than a REQUEST message 1321 for the base event. However, for interoperability reasons this is 1322 not recommended due to poor support in the wild for this type of 1323 message. 1325 The server MUST ensure participants are only sent information about 1326 recurrence instances they are added to when sending scheduling 1327 messages for recurring events. If the participant is not invited to 1328 the full recurring event but only individual instances, scheduling 1329 messages MUST be sent for just those expanded occurrences 1330 individually. If a participant is invited to a recurring event, but 1331 removed via a recurrence override from a particular instance, any 1332 scheduling messages to this participant MUST return the instance as 1333 "excluded" (if it matches a recurrence rule for the event) or omit 1334 the instance entirely (otherwise). 1336 If the event's "hideAttendees" property is set to "true", the 1337 recipient MUST be the only attendee in the message; all others are 1338 omitted. 1340 5.8.2.2. CANCEL 1342 When the server is the source for the event, a CANCEL message 1343 ([RFC5546], Section 3.2.5) is sent if any of: 1345 * A participant is removed from either the base event or a single 1346 instance (the message is only sent to this participant; remaining 1347 participants will get a REQUEST, as described above). 1349 * The event is destroyed. 1351 * An exclusion is added to recurrenceOverrides to remove an instance 1352 generated by the event's recurrence rule. 1354 * An additional instance (not generated by the event's recurrence 1355 rule) is removed from the recurrenceOverrides. 1357 In each of the latter 3 cases, the message is sent to all 1358 participants. 1360 5.8.2.3. REPLY 1362 When the server is _not_ the source for the event, a REPLY message 1363 ([RFC5546], Section 3.2.3) is sent for any participant corresponding 1364 to one of the user's ParticipantIdentitities in the account if any of 1365 the following changes are made by the user (_not_ by automatic 1366 processing of an iTIP message): 1368 * The "participationStatus" property of the participant is changed. 1370 * The event is destroyed and the participationStatus was not "needs- 1371 action". 1373 * The event is created and the participationStatus is not "needs- 1374 action". 1376 * An exclusion is added to recurrenceOverrides to remove an instance 1377 generated by the event's recurrence rule, and the 1378 participationStatus for this instance was not "needs-action". 1380 * An exclusion is removed from recurrenceOverrides (this is presumed 1381 to be the client undoing the deletion of a single instance), and 1382 the participationStatus for this instance is not "needs-action". 1384 * An instance not generated by the event's recurrence rule is 1385 removed from the recurrenceOverrides. 1387 * An instance not generated by the event's recurrence rule is added 1388 to the recurrenceOverrides (this is presumed to be the client 1389 undoing the deletion of a single instance). 1391 A reply is not sent when deleting an event where the current status 1392 is "needs-action" as if a junk calendar event gets added by an 1393 automated system, the user MUST be able to delete the event without 1394 sending a reply. 1396 5.9. CalendarEvent/copy 1398 This is a standard "/copy" method as described in [RFC8620], 1399 Section 5.4. 1401 5.10. CalendarEvent/query 1403 This is a standard "/query" method as described in [RFC8620], 1404 Section 5.5, with two extra arguments: 1406 * *expandRecurrences*: "Boolean" (default: false) If true, the 1407 server will expand any recurring event. If true, the filter MUST 1408 be just a FilterCondition (not a FilterOperator) and MUST include 1409 both a before and after property. This ensures the server is not 1410 asked to return an infinite number of results. 1412 * *timeZone*: "String" The time zone for before/after filter 1413 conditions (default: "Etc/UTC") 1415 If expandRecurrences is true, a separate id will be returned for each 1416 instance of a recurring event that matches the query. This synthetic 1417 id is opaque to the client, but allows the server to resolve the id + 1418 recurrence id for "/get" and "/set" operations. Otherwise, a single 1419 id will be returned for matching recurring events that represents the 1420 entire event. 1422 There is no necessary correspondence between the ids of different 1423 instances of the same expanded event. 1425 The following additional error may be returned instead of the 1426 "CalendarEvent/query" response: 1428 "cannotCalculateOccurrences": the server cannot expand a recurrence 1429 required to return the results for this query. 1431 5.10.1. Filtering 1433 A *FilterCondition* object has the following properties: 1435 * *inCalendars*: "Id[]|null" A list of calendar ids. An event must 1436 be in ANY of these calendars to match the condition. 1438 * *after*: "LocalDate|null" The end of the event, or any recurrence 1439 of the event, in the time zone given as the timeZone argument, 1440 must be after this date to match the condition. 1442 * *before*: "LocalDate|null" The start of the event, or any 1443 recurrence of the event, in the time zone given as the timeZone 1444 argument, must be before this date to match the condition. 1446 * *text*: "String|null" Looks for the text in the _title_, 1447 _description_, _locations_ (matching name/description), 1448 _participants_ (matching name/email) and any other textual 1449 properties of the event or any recurrence of the event. 1451 * *title*: "String|null" Looks for the text in the _title_ property 1452 of the event, or the overridden _title_ property of a recurrence. 1454 * *description*: "String|null" Looks for the text in the 1455 _description_ property of the event, or the overridden 1456 _description_ property of a recurrence. 1458 * *location*: "String|null" Looks for the text in the _locations_ 1459 property of the event (matching name/description of a location), 1460 or the overridden _locations_ property of a recurrence. 1462 * *owner*: "String|null" Looks for the text in the name or email 1463 fields of a participant in the _participants_ property of the 1464 event, or the overridden _participants_ property of a recurrence, 1465 where the participant has a role of "owner". 1467 * *attendee*: "String|null" Looks for the text in the name or email 1468 fields of a participant in the _participants_ property of the 1469 event, or the overridden _participants_ property of a recurrence, 1470 where the participant has a role of "attendee". 1472 * *participationStatus*: Must match. If owner/attendee condition, 1473 status must be of that participant. Otherwise any. 1475 * *uid*: "String" The uid of the event is exactly the given string. 1477 If expandRecurrences is true, all conditions must match against the 1478 same instance of a recurring event for the instance to match. If 1479 expandRecurrences is false, all conditions must match, but they may 1480 each match any instance of the event. 1482 If zero properties are specified on the FilterCondition, the 1483 condition MUST always evaluate to "true". If multiple properties are 1484 specified, ALL must apply for the condition to be "true" (it is 1485 equivalent to splitting the object into one-property conditions and 1486 making them all the child of an AND filter operator). 1488 The exact semantics for matching "String" fields is *deliberately not 1489 defined* to allow for flexibility in indexing implementation, subject 1490 to the following: 1492 * Text SHOULD be matched in a case-insensitive manner. 1494 * Text contained in either (but matched) single or double quotes 1495 SHOULD be treated as a *phrase search*, that is a match is 1496 required for that exact sequence of words, excluding the 1497 surrounding quotation marks. Use "\"", "\'" and "\\" to match a 1498 literal """, "'" and "\" respectively in a phrase. 1500 * Outside of a phrase, white-space SHOULD be treated as dividing 1501 separate tokens that may be searched for separately in the event, 1502 but MUST all be present for the event to match the filter. 1504 * Tokens MAY be matched on a whole-word basis using stemming (so for 1505 example a text search for "bus" would match "buses" but not 1506 "business"). 1508 5.10.2. Sorting 1510 The following properties MUST be supported for sorting: 1512 * start 1514 * uid 1516 * recurrenceId 1518 The following properties SHOULD be supported for sorting: 1520 * created 1522 * updated 1524 5.11. CalendarEvent/queryChanges 1526 This is a standard "/queryChanges" method as described in [RFC8620], 1527 Section 5.6. 1529 5.12. Examples 1531 TODO: Add example of how to get event by uid: query uid=foo and 1532 backref. Return multiple with recurrenceId set (user invited to 1533 specific instances of recurring event). 1535 6. Alerts 1537 Alerts may be specified on events as described in 1538 [I-D.ietf-calext-jscalendar], Section 4.5. 1540 Alerts MUST only be triggered for events in calendars where the user 1541 is subscribed and either the user owns the calendar or the calendar 1542 account's "shareesActAs" capability is "self". 1544 When an alert with an "email" action is triggered, the server MUST 1545 send an email to the user to notify them of the event. The contents 1546 of the email is implementation specific. Clients MUST NOT perform an 1547 action for these alerts. 1549 When an alert with a "display" action is triggered, clients SHOULD 1550 display an alert in a platform-appropriate manner to the user to 1551 remind them of the event. Clients with a full offline cache of 1552 events may choose to calculate when alerts should trigger locally. 1553 Alternatively, they can subscribe to push events from the server. 1555 6.1. Default alerts 1557 If the "useDefaultAlerts" property of an event is true, the alerts 1558 are taken from the "defaultAlertsWithTime" or 1559 "defaultAlertsWithoutTime" property of all Calendars the event is in, 1560 as described in Section XXX, rather than the "alerts" property of the 1561 CalendarEvent. 1563 When using default alerts, the "alerts" property of the event is 1564 ignored except for the following: 1566 * The "acknowledged" time for an alert is stored here when a default 1567 alert for the event is dismissed. The id of the alert MUST be the 1568 same as the id of the default alert in the calendar. See 1569 Section XXX on acknowledging alerts. 1571 * If an alert has a relatedTo property where the parent is the id of 1572 one of the calendar default alerts, it is processed as normal and 1573 not ignored. This is to support snoozing default alerts; see 1574 Section XXX. 1576 6.2. Acknowledging an alert 1578 To dismiss an alert, clients set the "acknowledged" property of the 1579 Alert object to the current date-time. If the alert was a calendar 1580 default, it may need to be added to the event at this point in order 1581 to acknowledge it. When other clients fetch the updated 1582 CalendarEvent they SHOULD automatically dismiss or suppress duplicate 1583 alerts (alerts with the same alert id that triggered on or before the 1584 "acknowledged" date-time) and alerts that have been removed from the 1585 event. 1587 Setting the "acknowledged" property MUST NOT create a new recurrence 1588 override. For a recurring calendar object, the "acknowledged" 1589 property of the parent object MUST be updated, unless the alert is 1590 already overridden in the "recurrenceOverrides" property. 1592 6.3. Snoozing an alert 1594 Users may wish to dismiss an alert temporarily and have it come back 1595 after a specific period of time. To do this, clients MUST: 1597 1. Acknowledge the alert as described in Section XXX. 1599 2. Add a new alert to the event with an "AbsoluteTrigger" for the 1600 date-time the alert has been snoozed until. Add a "relatedTo" 1601 property to the new alert, setting the "parent" relation to point 1602 to the original alert. This MUST NOT create a new recurrence 1603 override; it is added to the same "alerts" property that contains 1604 the alert that was acknowledged in step 1. 1606 When acknowledging a snoozed alert (i.e. one with a parent relatedTo 1607 pointing to the original alert), the client SHOULD delete the alert 1608 rather than setting the "acknowledged" property. 1610 6.4. Push events 1612 Servers that support the "urn:ietf:params:jmap:calendars" capability 1613 MUST support registering for the pseudo-type "CalendarAlert" in push 1614 subscriptions and event source connections, as described in 1615 [RFC8620], Sections 7.2 and 7.3. 1617 If requested, a CalendarAlert notification will be pushed whenever an 1618 alert is triggered for the user. For Event Source connections, this 1619 notification is pushed as an event called "calendarAlert". 1621 A *CalendarAlert* object has the following properties: 1623 * *@type*: "String" This MUST be the string "CalendarAlert". 1625 * *accountId*: "String" The account id for the calendar in which the 1626 alert triggered. 1628 * *calendarEventId*: "String" The CalendarEvent id for the alert 1629 that triggered. 1631 * *uid*: "String" The uid property of the CalendarEvent for the 1632 alert that triggered. 1634 * *recurrenceId*: "String|null" The recurrenceId for the instance of 1635 the event for which this alert is being triggered, or "null" if 1636 the event is not recurring. 1638 * *alertId*: "String" The id for the alert that triggered. 1640 7. Calendar Event Notifications 1642 The CalendarEventNotification data type records changes made by 1643 external entities to events in calendars the user is subscribed to. 1644 Notifications are stored in the same Account as the CalendarEvent 1645 that was changed. 1647 Notifications are only created by the server; users cannot create 1648 them directly. Clients SHOULD present the list of notifications to 1649 the user and allow them to dismiss them. To dismiss a notification 1650 you use a standard "/set" call to destroy it. 1652 The server SHOULD create a CalendarEventNotification whenever an 1653 event is added, updated or destroyed by another user or due to 1654 receiving an iTIP [RFC5546] or other scheduling message in a calendar 1655 this user is subscribed to. The server SHOULD NOT create 1656 notifications for events implicitly deleted due to the containing 1657 calendar being deleted. 1659 The CalendarEventNotification does not have any per-user data. A 1660 single instance may therefore be maintained on the server for all 1661 sharees of the notification. The server need only keep track of 1662 which users have yet to destroy the notification. 1664 7.1. Auto-deletion of Notifications 1666 The server MAY limit the maximum number of notifications it will 1667 store for a user. When the limit is reached, any new notification 1668 will cause the previously oldest notification to be automatically 1669 deleted. 1671 The server MAY coalesce events if appropriate, or remove events that 1672 it deems are no longer relevant or after a certain period of time. 1673 The server SHOULD automatically destroy a notification about an event 1674 if the user updates or destroys that event (e.g. if the user sends an 1675 RSVP for the event). 1677 7.2. Object Properties 1679 The *CalendarEventNotification* object has the following properties: 1681 * *id*: "String" The id of the CalendarEventNotification. 1683 * *created*: "UTCDate" The time this notification was created. 1685 * *changedBy*: "Person" Who made the change. 1687 - *name*: "String" The name of the person who made the change. 1689 - *email*: "String" The email of the person who made the change, 1690 or null if no email is available. 1692 - *principalId*: "String|null" The id of the calendar principal 1693 corresponding to the person who made the change, if any. This 1694 will be null if the change was due to receving an iTIP message. 1696 * *comment*: "String|null" Comment sent along with the change by the 1697 user that made it. (e.g. COMMENT property in an iTIP message). 1699 * *type*: "String" This MUST be one of 1701 - created 1703 - updated 1705 - destroyed 1707 * *calendarEventId*: "String" The id of the CalendarEvent that this 1708 notification is about. 1710 * *isDraft*: "Boolean" (created/updated only) Is this event a draft? 1711 * *event*: "JSEvent" The data before the change (if updated or 1712 destroyed), or the data after creation (if created). 1714 * *eventPatch*: "PatchObject" (updated only) A patch encoding the 1715 change between the data in the event property, and the data after 1716 the update. 1718 To reduce data, if the change only affects a single instance of a 1719 recurring event, the server MAY set the event and eventPatch 1720 properties for the instance; the calendarEventId MUST still be for 1721 the base event. 1723 7.3. CalendarEventNotification/get 1725 This is a standard "/get" method as described in [RFC8620], 1726 Section 5.1. 1728 7.4. CalendarEventNotification/changes 1730 This is a standard "/changes" method as described in [RFC8620], 1731 Section 5.2. 1733 7.5. CalendarEventNotification/set 1735 This is a standard "/changes" method as described in [RFC8620], 1736 Section 5.3. 1738 Only destroy is supported; any attempt to create/update MUST be 1739 rejected with a "forbidden" SetError. 1741 7.6. CalendarEventNotification/query 1743 This is a standard "/query" method as described in [RFC8620], 1744 Section 5.5. 1746 7.6.1. Filtering 1748 A *FilterCondition* object has the following properties: 1750 * *after*: "UTCDate|null" The creation date must be on or after this 1751 date to match the condition. 1753 * *before*: "UTCDate|null" The creation date must be before this 1754 date to match the condition. 1756 * *type*: "String" The type property must be the same to match the 1757 condition. 1759 * *calendarEventIds*: "Id[]|null" A list of event ids. The 1760 calendarEventId property of the notification must be in this list 1761 to match the condition. 1763 7.6.2. Sorting 1765 The "created" property MUST be supported for sorting. 1767 7.7. CalendarEventNotification/queryChanges 1769 This is a standard "/queryChanges" method as described in [RFC8620], 1770 Section 5.6. 1772 8. Security Considerations 1774 All security considerations of JMAP [RFC8620] and JSCalendar 1775 [I-D.ietf-calext-jscalendar] apply to this specification. Additional 1776 considerations specific to the data types and functionality 1777 introduced by this document are described in the following 1778 subsections. 1780 8.1. Denial-of-service Expanding Recurrences 1782 Recurrence rules can be crafted to occur as frequently as every 1783 second. Servers MUST be careful to not allow resources to be 1784 exhausted when expanding. Equally, rules can be generated that never 1785 create any occurrences at all. Servers MUST be careful to limit the 1786 work spent iterating in search of the next occurrence. 1788 8.2. Privacy 1790 TODO. 1792 9. IANA Considerations 1794 9.1. JMAP Capability Registration for "calendars" 1796 IANA will register the "calendars" JMAP Capability as follows: 1798 Capability Name: "urn:ietf:params:jmap:calendars" 1800 Specification document: this document 1802 Intended use: common 1804 Change Controller: IETF 1806 Security and privacy considerations: this document, Section XXX 1808 9.2. JSCalendar Property Registrations 1810 IANA will register the following additional properties in the 1811 JSCalendar Properties Registry. 1813 9.2.1. id 1815 Property Name: id 1817 Property Type: "Id" 1819 Property Context: JSEvent, JSTask 1821 Intended Use: Reserved 1823 9.2.2. calendarIds 1825 Property Name: calendarIds 1827 Property Type: "Id[Boolean]" 1829 Property Context: JSEvent, JSTask 1831 Intended Use: Reserved 1833 9.2.3. isDraft 1835 Property Name: isDraft 1837 Property Type: "Boolean" 1839 Property Context: JSEvent, JSTask 1841 Intended Use: Reserved 1843 9.2.4. utcStart 1845 Property Name: utcStart 1847 Property Type: "UTCDateTime" 1849 Property Context: JSEvent, JSTask 1851 Intended Use: Reserved 1853 9.2.5. utcEnd 1855 Property Name: utcEnd 1857 Property Type: "UTCDateTime" 1859 Property Context: JSEvent, JSTask 1861 Intended Use: Reserved 1863 9.2.6. mayInviteSelf 1865 Property Name: mayInviteSelf 1867 Property Type: "Boolean" (default: false) 1869 Property Context: JSEvent, JSTask 1871 Reference: This document, Section XXX. 1873 Intended Use: Common 1875 9.2.7. mayInviteOthers 1877 Property Name: mayInviteOthers 1879 Property Type: "Boolean" (default: false) 1881 Property Context: JSEvent, JSTask 1883 Reference: This document, Section XXX. 1885 Intended Use: Common 1887 9.2.8. hideAttendees 1889 Property Name: hideAttendees 1891 Property Type: "Boolean" (default: false) 1893 Property Context: JSEvent, JSTask 1895 Reference: This document, Section XXX. 1897 Intended Use: Common 1899 10. Normative References 1901 [I-D.ietf-calext-jscalendar] 1902 Jenkins, N. and R. Stepanek, "JSCalendar: A JSON 1903 Representation of Calendar Data", Work in Progress, 1904 Internet-Draft, draft-ietf-calext-jscalendar-32, 15 1905 October 2020, . 1908 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 1909 Requirement Levels", BCP 14, RFC 2119, 1910 DOI 10.17487/RFC2119, March 1997, 1911 . 1913 [RFC2397] Masinter, L., "The "data" URL scheme", RFC 2397, 1914 DOI 10.17487/RFC2397, August 1998, 1915 . 1917 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 1918 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 1919 May 2017, . 1921 [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application 1922 Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July 1923 2019, . 1925 11. Informative References 1927 [RFC4791] Daboo, C., Desruisseaux, B., and L. Dusseault, 1928 "Calendaring Extensions to WebDAV (CalDAV)", RFC 4791, 1929 DOI 10.17487/RFC4791, March 2007, 1930 . 1932 [RFC5546] Daboo, C., Ed., "iCalendar Transport-Independent 1933 Interoperability Protocol (iTIP)", RFC 5546, 1934 DOI 10.17487/RFC5546, December 2009, 1935 . 1937 [RFC6047] Melnikov, A., Ed., "iCalendar Message-Based 1938 Interoperability Protocol (iMIP)", RFC 6047, 1939 DOI 10.17487/RFC6047, December 2010, 1940 . 1942 Authors' Addresses 1943 Neil Jenkins (editor) 1944 Fastmail 1945 PO Box 234, Collins St West 1946 Melbourne VIC 8007 1947 Australia 1949 Email: neilj@fastmailteam.com 1950 URI: https://www.fastmail.com 1952 Michael Douglass (editor) 1953 Spherical Cow Group 1954 226 3rd Street 1955 Troy, NY 12180 1956 United States of America 1958 Email: mdouglass@sphericalcowgroup.com 1959 URI: http://sphericalcowgroup.com