idnits 2.17.1 draft-ietf-jmap-calendars-08.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: ---------------------------------------------------------------------------- == There are 4 instances of lines with non-ascii characters in the document. 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 (24 February 2022) is 792 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 324, but not defined == Missing Reference: 'String' is mentioned on line 472, but not defined == Missing Reference: 'Boolean' is mentioned on line 1951, but not defined Summary: 1 error (**), 0 flaws (~~), 5 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 August 2022 Spherical Cow Group 6 24 February 2022 8 JMAP for Calendars 9 draft-ietf-jmap-calendars-08 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 August 2022. 33 Copyright Notice 35 Copyright (c) 2022 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 Revised BSD License text as 44 described in Section 4.e of the Trust Legal Provisions and are 45 provided without warranty as described in the Revised BSD License. 47 Table of Contents 49 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 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 . . . . . . . . . . . . . . . . . . . 5 54 1.4.1. UIDs and CalendarEvent Ids . . . . . . . . . . . . . 6 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:calendars:preferences . . . . . 7 58 1.5.3. urn:ietf:params:jmap:principals:availability . . . . 7 59 2. Principals and Sharing . . . . . . . . . . . . . . . . . . . 8 60 2.1. Principal Capability urn:ietf:params:jmap:calendars . . . 8 61 2.2. Principal/getAvailability . . . . . . . . . . . . . . . . 8 62 3. Participant Identities . . . . . . . . . . . . . . . . . . . 10 63 3.1. ParticipantIdentity/get . . . . . . . . . . . . . . . . . 11 64 3.2. ParticipantIdentity/changes . . . . . . . . . . . . . . . 11 65 3.3. ParticipantIdentity/set . . . . . . . . . . . . . . . . . 11 66 4. Calendars . . . . . . . . . . . . . . . . . . . . . . . . . . 11 67 4.1. Calendar/get . . . . . . . . . . . . . . . . . . . . . . 15 68 4.2. Calendar/changes . . . . . . . . . . . . . . . . . . . . 16 69 4.3. Calendar/set . . . . . . . . . . . . . . . . . . . . . . 16 70 5. Calendar Events . . . . . . . . . . . . . . . . . . . . . . . 17 71 5.1. Additional JSCalendar properties . . . . . . . . . . . . 19 72 5.1.1. mayInviteSelf . . . . . . . . . . . . . . . . . . . . 19 73 5.1.2. mayInviteOthers . . . . . . . . . . . . . . . . . . . 19 74 5.1.3. hideAttendees . . . . . . . . . . . . . . . . . . . . 19 75 5.2. Attachments . . . . . . . . . . . . . . . . . . . . . . . 20 76 5.3. Per-user properties . . . . . . . . . . . . . . . . . . . 20 77 5.4. Recurring events . . . . . . . . . . . . . . . . . . . . 20 78 5.5. Updating for "this-and-future" . . . . . . . . . . . . . 21 79 5.5.1. Splitting an event . . . . . . . . . . . . . . . . . 21 80 5.5.2. Updating the base event and overriding previous . . . 21 81 5.6. CalendarEvent/get . . . . . . . . . . . . . . . . . . . . 21 82 5.7. CalendarEvent/changes . . . . . . . . . . . . . . . . . . 23 83 5.8. CalendarEvent/set . . . . . . . . . . . . . . . . . . . . 23 84 5.8.1. Patching . . . . . . . . . . . . . . . . . . . . . . 26 85 5.8.2. Sending invitations and responses . . . . . . . . . . 29 86 5.9. CalendarEvent/copy . . . . . . . . . . . . . . . . . . . 32 87 5.10. CalendarEvent/query . . . . . . . . . . . . . . . . . . . 32 88 5.10.1. Filtering . . . . . . . . . . . . . . . . . . . . . 32 89 5.10.2. Sorting . . . . . . . . . . . . . . . . . . . . . . 34 90 5.11. CalendarEvent/queryChanges . . . . . . . . . . . . . . . 34 91 5.12. Examples . . . . . . . . . . . . . . . . . . . . . . . . 34 92 6. Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 93 6.1. Default alerts . . . . . . . . . . . . . . . . . . . . . 35 94 6.2. Acknowledging an alert . . . . . . . . . . . . . . . . . 35 95 6.3. Snoozing an alert . . . . . . . . . . . . . . . . . . . . 35 96 6.4. Push events . . . . . . . . . . . . . . . . . . . . . . . 36 97 7. Calendar Event Notifications . . . . . . . . . . . . . . . . 36 98 7.1. Auto-deletion of Notifications . . . . . . . . . . . . . 37 99 7.2. Object Properties . . . . . . . . . . . . . . . . . . . . 37 100 7.3. CalendarEventNotification/get . . . . . . . . . . . . . . 38 101 7.4. CalendarEventNotification/changes . . . . . . . . . . . . 38 102 7.5. CalendarEventNotification/set . . . . . . . . . . . . . . 38 103 7.6. CalendarEventNotification/query . . . . . . . . . . . . . 38 104 7.6.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 38 105 7.6.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 39 106 7.7. CalendarEventNotification/queryChanges . . . . . . . . . 39 107 8. CalendarPreferences . . . . . . . . . . . . . . . . . . . . . 39 108 8.1. CalendarPreferences/get . . . . . . . . . . . . . . . . . 39 109 8.2. CalendarPreferences/set . . . . . . . . . . . . . . . . . 40 110 9. Security Considerations . . . . . . . . . . . . . . . . . . . 40 111 9.1. Privacy . . . . . . . . . . . . . . . . . . . . . . . . . 40 112 9.2. Spoofing . . . . . . . . . . . . . . . . . . . . . . . . 40 113 9.3. Denial-of-service . . . . . . . . . . . . . . . . . . . . 41 114 9.3.1. Expanding Recurrences . . . . . . . . . . . . . . . . 41 115 9.3.2. Firing alerts . . . . . . . . . . . . . . . . . . . . 41 116 9.3.3. Load spikes . . . . . . . . . . . . . . . . . . . . . 41 117 9.4. Spam . . . . . . . . . . . . . . . . . . . . . . . . . . 42 118 10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 42 119 10.1. JMAP Capability Registration for "calendars" . . . . . . 42 120 10.2. JMAP Capability Registration for 121 "calendars:preferences" . . . . . . . . . . . . . . . . 42 122 10.3. JMAP Capability Registration for 123 "principals:availability" . . . . . . . . . . . . . . . 43 124 10.4. JSCalendar Property Registrations . . . . . . . . . . . 43 125 10.4.1. id . . . . . . . . . . . . . . . . . . . . . . . . . 43 126 10.4.2. calendarIds . . . . . . . . . . . . . . . . . . . . 43 127 10.4.3. isDraft . . . . . . . . . . . . . . . . . . . . . . 43 128 10.4.4. utcStart . . . . . . . . . . . . . . . . . . . . . . 44 129 10.4.5. utcEnd . . . . . . . . . . . . . . . . . . . . . . . 44 130 10.4.6. mayInviteSelf . . . . . . . . . . . . . . . . . . . 44 131 10.4.7. mayInviteOthers . . . . . . . . . . . . . . . . . . 44 132 10.4.8. hideAttendees . . . . . . . . . . . . . . . . . . . 45 133 11. Normative References . . . . . . . . . . . . . . . . . . . . 45 134 12. Informative References . . . . . . . . . . . . . . . . . . . 45 135 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 46 137 1. Introduction 139 JMAP ([RFC8620] – (U+2013) JSON Meta Application Protocol) is a 140 generic protocol for synchronizing data, such as mail, calendars or 141 contacts, between a client and a server. It is optimized for mobile 142 and web environments, and aims to provide a consistent interface to 143 different data types. 145 This specification defines a data model for synchronizing calendar 146 data between a client and a server using JMAP. The data model is 147 designed to allow a server to provide consistent access to the same 148 data via CalDAV [RFC4791] as well as JMAP, however the functionality 149 offered over the two protocols may differ. Unlike CalDAV, this 150 specification does not define access to tasks or journal entries 151 (VTODO or VJOURNAL iCalendar components in CalDAV). 153 1.1. Notational Conventions 155 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 156 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 157 "OPTIONAL" in this document are to be interpreted as described in BCP 158 14 [RFC2119] [RFC8174] when, and only when, they appear in all 159 capitals, as shown here. 161 Type signatures, examples, and property descriptions in this document 162 follow the conventions established in Section 1.1 of [RFC8620]. Data 163 types defined in the core specification are also used in this 164 document. 166 1.2. The LocalDate Data Type 168 Where LocalDate is given as a type, it means a string in the same 169 format as Date (see [RFC8620], Section 1.4), but with the time-offset 170 omitted from the end. The interpretation in absolute time depends 171 upon the time zone for the event, which may not be a fixed offset 172 (for example when daylight saving time occurs). For example, 173 2014-10-30T14:12:00. 175 1.3. Terminology 177 The same terminology is used in this document as in the core JMAP 178 specification, see [RFC8620], Section 1.6. 180 The terms ParticipantIdentity, Calendar, CalendarEvent, 181 CalendarEventNotification, and CalendarPreferences (with these 182 specific capitalizations) are used to refer to the data types defined 183 in this document and instances of those data types. 185 1.4. Data Model Overview 187 An Account (see [RFC8620], Section 1.6.2) with support for the 188 calendar data model contains zero or more Calendar objects, which is 189 a named collection of CalendarEvents. Calendars can also provide 190 defaults, such as alerts and a color to apply to events in the 191 calendar. Clients commonly let users toggle visibility of events 192 belonging to a particular calendar on/off. Servers may allow an 193 event to belong to multiple Calendars within an account. 195 A CalendarEvent is a representation of an event or recurring series 196 of events in JSEvent [RFC8984] format. Simple clients may ask the 197 server to expand recurrences for them within a specific time period, 198 and optionally convert times into UTC so they do not have to handle 199 time zone conversion. More full-featured clients will want to access 200 the full event information and handle recurrence expansion and time 201 zone conversion locally. 203 CalendarEventNotification objects keep track of the history of 204 changes made to a calendar by other users, allowing calendar clients 205 to notify the user of changes to their schedule. 207 The ParticipantIdentity data type represents the identities of the 208 current user within an Account, which determines which events the 209 user is a participant of and possibly their permissions related to 210 that event. 212 The CalendarPreferences object is a singleton in the account that 213 stores the user's default calendar and participant identity. 215 In servers with support for JMAP Sharing [RFC XXX], data may be 216 shared with other users. Sharing permissions are managed per 217 calendar. For example, an individual may have separate calendars for 218 personal and work activities, with both contributing to their free- 219 busy availability, but only the work calendar shared in its entirety 220 with colleagues. Principals may also represent schedulable entities, 221 such as a meeting room. 223 Users can normally subscribe to any calendar to which they have 224 access. This indicates the user wants this calendar to appear in 225 their regular list of calendars. The separate "isVisible" property 226 stores whether the user would currently like to view the events in a 227 subscribed calendar. 229 1.4.1. UIDs and CalendarEvent Ids 231 Each CalendarEvent has a uid property ([RFC8984], Section 4.1.2), 232 which is a globally unique identifier that identifies the same event 233 in different Accounts, or different instances of the same recurring 234 event within an Account. 236 An Account MUST NOT contain more than one CalendarEvent with the same 237 uid unless all of the CalendarEvent objects have distinct, non-null 238 values for their recurrenceId property. (This situation occurs if 239 the principal is added to one or more specific instances of a 240 recurring event without being invited to the whole series.) 242 Each CalendarEvent also has an id, which is scoped to the JMAP 243 Account and used for referencing it in JMAP methods. There is no 244 necessary link between the uid property and the CalendarEvent's id. 245 CalendarEvents with the same uid in different Accounts MAY have 246 different ids. 248 1.5. Addition to the Capabilities Object 250 The capabilities object is returned as part of the JMAP Session 251 object; see [RFC8620], Section 2. This document defines two 252 additional capability URIs. 254 1.5.1. urn:ietf:params:jmap:calendars 256 This represents support for the Calendar, CalendarEvent, 257 CalendarEventNotification, and ParticipantIdentity data types and 258 associated API methods. The value of this property in the JMAP 259 Session capabilities property is an empty object. 261 The value of this property in an account’ (U+2019)s 262 accountCapabilities property is an object that MUST contain the 263 following information on server capabilities and permissions for that 264 account: 266 * *shareesActAs*: String This MUST be one of: 268 - self - sharees act as themselves when using calendars in this 269 account. 270 - secretary- sharees act as the principal to which this account 271 belongs. 273 * *maxCalendarsPerEvent*: UnsignedInt|null The maximum number of 274 Calendars (see Section XXX) that can be can assigned to a single 275 CalendarEvent object (see Section XXX). This MUST be an integer 276 >= 1, or null for no limit (or rather, the limit is always the 277 number of Calendars in the account). 279 * *minDateTime*: LocalDate The earliest date-time the server is 280 willing to accept for any date stored in a CalendarEvent. 282 * *maxDateTime*: LocalDate The latest date-time the server is 283 willing to accept for any date stored in a CalendarEvent. 285 * *maxExpandedQueryDuration*: Duration The maximum duration the user 286 may query over when asking the server to expand recurrences. 288 * *maxParticipantsPerEvent*: Number|null The maximum number of 289 participants a single event may have, or null for no limit. 291 * *mayCreateCalendar*: Boolean If true, the user may create a 292 calendar in this account. 294 1.5.2. urn:ietf:params:jmap:calendars:preferences 296 This represents support for the CalendarPreferences data type and 297 associated API methods. The value of this property in the JMAP 298 Session capabilities property and the account’ (U+2019)s 299 accountCapabilities property is an empty object. 301 Any account with this capability MUST also have the 302 urn:ietf:params:jmap:calendars capability. 304 1.5.3. urn:ietf:params:jmap:principals:availability 306 Represents support for the Principal/getAvailability method. Any 307 account with this capability MUST also have the 308 urn:ietf:params:jmap:principals capability (see [RFC XXX]). 310 The value of this property in the JMAP Session capabilities property 311 is an empty object. 313 The value of this property in an account’ (U+2019)s 314 accountCapabilities property is an object that MUST contain the 315 following information on server capabilities and permissions for that 316 account: 318 * *maxAvailabilityDuration*: The maximum duration over which the 319 server is prepared to calculate availability in a single call (see 320 Section XXX). 322 2. Principals and Sharing 324 For systems that also support JMAP Sharing [RFC XXX], the calendars 325 capability is used to indicate that this principal may be used with 326 calendaring. A new method is defined to allow users to query 327 availability when scehduling events. 329 2.1. Principal Capability urn:ietf:params:jmap:calendars 331 A "urn:ietf:params:jmap:calendars" property is added to the Principal 332 "capabilities" object, the value of which is an object with the 333 following properties: 335 * *accountId*: Id|null Id of Account with the 336 urn:ietf:params:jmap:calendars capability that contains the 337 calendar data for this principal, or null if none (e.g. the 338 Principal is a group just used for permissions management), or the 339 user does not have access to any data in the account (with the 340 exception of free/busy, which is governed by the 341 mayGetAvailability property). 342 * *account*: Account|null The JMAP Account object corresponding to 343 the accountId, null if none. 344 * *mayGetAvailability*: Boolean May the user call the "Principal/ 345 getAvailability" method with this Principal? 346 * *mayShareWith*: Boolean May the user add this principal as a 347 calendar sharee (by adding them to the shareWith property of a 348 calendar, see Section XXX)? 349 * *sendTo*: String[String]|null If this principal may be added as a 350 participant to an event, this is the map of methods for adding it, 351 in the same format as Participant#sendTo in JSEvent (see 352 [RFC8984], Section 4.4.5). 354 2.2. Principal/getAvailability 356 This method calculates the availability of the principal for 357 scheduling within a requested time period. It takes the following 358 arguments: 360 * *accountId*: Id The id of the account to use. 361 * *id*: Id The id of the Principal to calculate availability for. 362 * *utcStart*: UTCDate The start time (inclusive) of the period for 363 which to return availability. 364 * *utcEnd*: UTCDate The end time (exclusive) of the period for which 365 to return availability. 366 * *showDetails*: Boolean If true, event details will be returned if 367 the user has permission to view them. 369 * *eventProperties*: String[]|null A list of properties to include 370 in any JSEvent object returned. If null, all properties of the 371 event will be returned. Otherwise, only properties with names in 372 the given list will be returned. 374 The server will first find all relevant events, expanding any 375 recurring events. Relevant events are ones where all of the 376 following is true: 378 * The principal is subscribed to the calendar. 379 * Either the calendar belongs to the principal or the calendar 380 account's "shareesActAs" property is "self". 381 * The "includeInAvailability" property of the calendar for the 382 principal is "all" or "attending". 383 * The user has the "mayReadFreeBusy" permission for the calendar. 384 * The event finishes after the "utcStart" argument and starts before 385 the "utcEnd" argument. 386 * The event's "privacy" property is not "secret". 387 * The "freeBusyStatus" property of the event is "busy" (or omitted, 388 as this is the default). 389 * The "status" property of the event is not "cancelled". 390 * If the "includeInAvailability" property of the calendar is 391 "attending", then the principal is a participant of the event, and 392 has a "participationStatus" of "accepted" or "tentative". 394 If an event is in more than one calendar, it is relevant if all of 395 the above are true for any one calendar that it is in. 397 The server then generates a BusyPeriod object for each of these 398 events. A *BusyPeriod* object has the following properties: 400 * *utcStart*: UTCDate The start time (inclusive) of the period this 401 represents. 403 * *utcEnd*: UTCDate The end time (exclusive) of the period this 404 represents. 406 * *busyStatus*: String (optional, default "unavailable") This MUST 407 be one of 409 - confirmed: The event status is "confirmed". 410 - tentative: The event status is "tentative". 411 - unavailable: The principal is not available for scheduling at 412 this time for any other reason. 414 * *event*: JSEvent|null The JSEvent representation of the event, or 415 null if any of the following are true: 417 - The "showDetails" argument is false. 418 - The "privacy" property of the event is "private". 419 - The user does not have the "mayReadItems" permission for any of 420 the calendars the event is in. 422 If an eventProperties argument was given, any properties in the 423 JSEvent that are not in the eventProperties list are removed from 424 the returned representation. 426 The server MAY also generate BusyPeriod objects based on other 427 information it has about the principal's availability, such as office 428 hours. 430 Finally, the server MUST merge and split BusyPeriod objects where the 431 "event" property is null, such that none of them overlap and either 432 there is a gap in time between any two objects (the utcEnd of one 433 does not equal the utcStart of another) or those objects have a 434 different busyStatus property. If there are overlapping BusyPeriod 435 time ranges with different "busyStatus" properties the server MUST 436 choose the value in the following order: confirmed > unavailable > 437 tentative. 439 The response has the following argument: 441 * *list*: BusyPeriod[] The list of BusyPeriod objects calculated as 442 described above. 444 The following additional errors may be returned instead of the 445 "Principal/getAvailability" response: 447 notFound: No principal with this id exists, or the user does not have 448 permission to see that this principal exists. 450 forbidden: The user does not have permission to query this 451 principal's availability. 453 tooLarge: The duration between utcStart an utcEnd is longer than the 454 server is willing to calculate availability for. 456 rateLimit: Too many availability requests have been made recently and 457 the user is being rate limited. It may work to try again later. 459 3. Participant Identities 461 A ParticipantIdentity stores information about a URI that represents 462 the user within that account in an event's participants. It has the 463 following properties: 465 * *id*: Id (immutable; server-set) The id of the 466 ParticipantIdentity. 468 * *name*: String (default: "") The display name of the participant 469 to use when adding this participant to an event, e.g. "Joe 470 Bloggs". 472 * *sendTo*: String[String] Represents methods by which the 473 participant may receive invitations and updates to an event. 475 The keys in the property value are the available methods and MUST 476 only contain ASCII alphanumeric characters (A-Za-z0-9). The value 477 is a URI for the method specified in the key. 479 A participant in an event corresponds to a ParticipantIdentity if any 480 of the method/uri pairs in the sendTo property of the participant are 481 identical to a method/uri pair in the sendTo property of the 482 identity. 484 The following JMAP methods are supported. 486 3.1. ParticipantIdentity/get 488 This is a standard "/get" method as described in [RFC8620], 489 Section 5.1. The _ids_ argument may be null to fetch all at once. 491 3.2. ParticipantIdentity/changes 493 This is a standard "/changes" method as described in [RFC8620], 494 Section 5.2. 496 3.3. ParticipantIdentity/set 498 This is a standard "/set" method as described in [RFC8620], 499 Section 5.3. The server MAY restrict the uri values the user may 500 claim, for example only allowing mailto: URIs with email addresses 501 that belong to the user. A standard forbidden error is returned to 502 reject non-permissible changes. 504 A participant identity may be destroyed that is referenced as the 505 "defaultParticipantIdentityId" in the CalenderPreferences object for 506 the same account. Doing so updates the defaultParticipantIdentityId 507 property on the CalendarPreferences to null. 509 4. Calendars 511 A Calendar is a named collection of events. All events are 512 associated with at least one calendar. 514 A *Calendar* object has the following properties: 516 * *id*: Id (immutable; server-set) The id of the calendar. 517 * *name*: String The user-visible name of the calendar. This may be 518 any UTF-8 string of at least 1 character in length and maximum 255 519 octets in size. 520 * *description*: String|null (default: null) An optional longer-form 521 description of the calendar, to provide context in shared 522 environments where users need more than just the name. 523 * *color*: String|null (default: null) A color to be used when 524 displaying events associated with the calendar. 526 If not null, the value MUST be a case-insensitive color name taken 527 from the set of names defined in Section 4.3 of CSS Color Module 528 Level 3 COLORS (https://www.w3.org/TR/css-color-3/), or an RGB value 529 in hexadecimal notation, as defined in Section 4.2.1 of CSS Color 530 Module Level 3. 532 The color SHOULD have sufficient contrast to be used as text on a white background. 534 * *sortOrder*: UnsignedInt (default: 0) Defines the sort order of 535 calendars when presented in the client's UI, so it is consistent 536 between devices. The number MUST be an integer in the range 0 <= 537 sortOrder < 2^(31.) 539 A calendar with a lower order should be displayed before a 540 calendar with a higher order in any list of calendars in the 541 client's UI. Calendars with equal order SHOULD be sorted in 542 alphabetical order by name. The sorting should take into account 543 locale-specific character order convention. 545 * *isSubscribed*: Boolean Has the user indicated they wish to see 546 this Calendar in their client? This SHOULD default to false for 547 Calendars in shared accounts the user has access to and true for 548 any new Calendars created by the user themself. 550 If false, the calendar should only be displayed when the user 551 explicitly requests it or to offer it for the user to subscribe 552 to. 554 * *isVisible*: Boolean (default: true) Should the calendar's events 555 be displayed to the user at the moment? Clients MUST ignore this 556 property if isSubscribed is false. If an event is in multiple 557 calendars, it should be displayed if isVisible is true for any of 558 those calendars. 560 * *includeInAvailability*: String (default: all) Should the 561 calendar's events be used as part of availability calculation? 562 This MUST be one of: 564 - all: all events are considered. 565 - attending: events the user is a confirmed or tentative 566 participant of are considered. 567 - none: all events are ignored (but may be considered if also in 568 another calendar). 570 * *defaultAlertsWithTime*: Id[Alert]|null (default: null) A map of 571 alert ids to Alert objects (see [RFC8984], Section 4.5.2) to apply 572 for events where "showWithoutTime" is false and "useDefaultAlerts" 573 is true. Ids MUST be unique across all default alerts in the 574 account, including those in other calendars; a UUID is 575 recommended. 577 * *defaultAlertsWithoutTime*: Id[Alert]|null (default: null) A map 578 of alert ids to Alert objects (see [RFC8984], Section 4.5.2) to 579 apply for events where "showWithoutTime" is true and 580 "useDefaultAlerts" is true. Ids MUST be unique across all default 581 alerts in the account, including those in other calendars; a UUID 582 is recommended. 584 * *timeZone*: String|null (default: null) The time zone to use for 585 events without a time zone when the server needs to resolve them 586 into absolute time, e.g., for alerts or availability calculation. 587 The value MUST be a time zone id from the IANA Time Zone Database 588 TZDB (https://www.iana.org/time-zones). If null, the timeZone of 589 the account's associated Principal will be used. Clients SHOULD 590 use this as the default for new events in this calendar if set. 592 * *shareWith*: Id[CalendarRights]|null (default: null) A map of 593 Principal id to rights for principals this calendar is shared 594 with. The principal to which this calendar belongs MUST NOT be in 595 this set. This is null if the user requesting the object does not 596 have the mayAdmin right, or if the calendar is not shared with 597 anyone. May be modified only if the user has the mayAdmin right. 598 The account id for the principals may be found in the 599 urn:ietf:params:jmap:principals:owner capability of the Account to 600 which the calendar belongs. 602 * *myRights*: CalendarRights (server-set) The set of access rights 603 the user has in relation to this Calendar. If any event is in 604 multiple calendars, the user has the following rights: 606 - The user may fetch the event if they have the mayReadItems 607 right on any calendar the event is in. 609 - The user may remove an event from a calendar (by modifying the 610 event's "calendarIds" property) if the user has the appropriate 611 permission for that calendar. 612 - The user may make other changes to the event if they have the 613 right to do so in _all_ calendars to which the event belongs. 615 A *CalendarRights* object has the following properties: 617 * *mayReadFreeBusy*: Boolean The user may read the free-busy 618 information for this calendar as part of a call to Principal/ 619 getAvailability (see Section XXX). 621 * *mayReadItems*: Boolean The user may fetch the events in this 622 calendar. 624 * *mayWriteAll*: Boolean The user may create, modify or destroy all 625 events in this calendar, or move events to or from this calendar. 626 If this is true, the mayWriteOwn, mayUpdatePrivate and mayRSVP 627 properties MUST all also be true. 629 * *mayWriteOwn*: Boolean The user may create, modify or destroy an 630 event on this calendar if either they are the owner of the event 631 or the event has no owner. This means the user may also transfer 632 ownership by updating an event so they are no longer an owner. 634 * *mayUpdatePrivate*: Boolean The user may modify the following 635 properties on all events in the calendar, even if they would not 636 otherwise have permission to modify that event. If the 637 shareesActAs account capability is "self", these properties MUST 638 all be stored per-user, and changes do not affect any other user 639 of the calendar. If shareesActAs is "secretary", the values are 640 shared between all users. 642 - keywords 643 - color 644 - freeBusyStatus 645 - useDefaultAlerts 646 - alerts 648 The user may also modify the above on a per-occurrence basis for 649 recurring events (updating the recurrenceOverrides property of the 650 event to do so). 652 * *mayRSVP*: Boolean The user may modify the following properties of 653 any Participant object that corresponds to one of the user's 654 ParticipantIdentity objects in the account, even if they would not 655 otherwise have permission to modify that event: 657 - participationStatus 658 - participationComment 659 - expectReply 660 - scheduleAgent 661 - scheduleSequence 662 - scheduleUpdated 664 If the event has its "mayInviteSelf" property set to true (see 665 Section XXX), then the user may also add a new Participant to the 666 event with a sendTo property that is the same as the sendTo 667 property of one of the user's ParticipantIdentity objects in the 668 account. The roles property of the participant MUST only contain 669 "attendee". 671 If the event has its "mayInviteOthers" property set to true (see 672 Section XXX) and there is an existing Participant in the event 673 corresponding to one of the user's ParticipantIdentity objects in 674 the account, then the user may also add new participants. The 675 roles property of any new participant MUST only contain 676 "attendee". 678 The user may also do all of the above on a per-occurrence basis 679 for recurring events (updating the recurrenceOverrides property of 680 the event to do so). 682 * *mayAdmin*: Boolean The user may modify sharing for this calendar. 684 * *mayDelete*: Boolean (server-set) The user may delete the calendar 685 itself. This property MUST be false if the account to which this 686 calendar belongs has the _isReadOnly_ property set to true. 688 The user is an *owner* for an event if the CalendarEvent object has a 689 "participants" property, and one of the Participant objects both: 691 a) Has the "owner" role. 692 b) Corresponds to one of the user's ParticipantIdentity objects in the account. 694 An event has no owner if its participants property is null or 695 omitted, or if none of the Participant objects have the "owner" role. 697 4.1. Calendar/get 699 This is a standard "/get" method as described in [RFC8620], 700 Section 5.1. The _ids_ argument may be null to fetch all at once. 702 If mayReadFreeBusy is the only permission the user has, the calendar 703 MUST NOT be returned in Calendar/get and Calendar/query; it must 704 behave as though it did not exist. The data is just used as part of 705 Principal/getAvailability. 707 4.2. Calendar/changes 709 This is a standard "/changes" method as described in [RFC8620], 710 Section 5.2. 712 4.3. Calendar/set 714 This is a standard "/set" method as described in [RFC8620], 715 Section 5.3 but with the following additional request argument: 717 * *onDestroyRemoveEvents*: Boolean (default: false) 719 If false, any attempt to destroy a Calendar that still has 720 CalendarEvents in it will be rejected with a calendarHasEvent 721 SetError. If true, any CalendarEvents that were in the Calendar will 722 be removed from it, and if in no other Calendars they will be 723 destroyed. This SHOULD NOT send scheduling messages to participants 724 or create CalendarEventNotification objects. 726 The "shareWith" property may only be set by users that have the 727 mayAdmin right. The value is shared across all users, although users 728 without the mayAdmin right cannot see the value. 730 When modifying the shareWith property, the user cannot give a right 731 to a principal if the principal did not already have that right and 732 the user making the change also does not have that right. Any 733 attempt to do so must be rejected with a forbidden SetError. 735 Users can subscribe or unsubscribe to a calendar by setting the 736 "isSubscribed" property. The server MAY forbid users from 737 subscribing to certain calendars even though they have permission to 738 see them, rejecting the update with a forbidden SetError. 740 The "timeZone", "includeInAvailability", "defaultAlertsWithoutTime" 741 and "defaultAlertsWithTime" properties are stored per-user if the 742 calendar account's "shareesActAs" capability is "self", and may be 743 set by any user who is subscribed to the calendar. Each user gets 744 the default value for these properties as the initial value; they do 745 not inherit an initial value from the calendar owner. 747 If the calendar account's "shareesActAs" capability is "self" these 748 properties are instead shared, and may only be set by users that have 749 the mayAdmin right. 751 The following properties may be set by anyone who is subscribed to 752 the calendar and are always stored per-user: 754 * name 755 * color 756 * sortOrder 757 * isVisible 759 The "name" and "color" properties are initially inherited from the 760 owner's copy of the calendar, but if set by a sharee that user gets 761 their own copy of the property; it does not change for any other 762 principals. If the value of the property in the owner's calendar 763 changes after this, it does not overwrite the sharee's value. 765 The "sortOrder" and "isVisible" properties are initally the default 766 value for each sharee; they are not inherited from the owner. 768 A calendar may be destroyed that is referenced as the 769 "defaultCalendarId" in the CalenderPreferences object for the same 770 account. Doing so updates the defaultCalendarId property on the 771 CalendarPreferences to null. 773 The following extra SetError types are defined: 775 For "destroy": 777 * *calendarHasEvent*: The Calendar has at least one CalendarEvent 778 assigned to it, and the "onDestroyRemoveEvents" argument was 779 false. 781 5. Calendar Events 783 A *CalendarEvent* object contains information about an event, or 784 recurring series of events, that takes place at a particular time. 785 It is a JSEvent object, as defined in [RFC8984], with the following 786 additional properties: 788 * *id*: Id (immutable; server-set) The id of the CalendarEvent. The 789 id uniquely identifies a JSEvent with a particular "uid" and 790 "recurrenceId" within a particular account. 792 * *baseEventId*: Id|null (immutable; server-set) This is only 793 defined if the _id_ property is a synthetic id, generated by the 794 server to represent a particular instance of a recurring event 795 (see Section XXX). This property gives the id of the "real" 796 CalendarEvent this was generated from. 798 * *calendarIds*: Id[Boolean] The set of Calendar ids this event 799 belongs to. An event MUST belong to one or more Calendars at all 800 times (until it is destroyed). The set is represented as an 801 object, with each key being a _Calendar id_. The value for each 802 key in the object MUST be true. 804 * *isDraft*: Boolean (default: false) If true, this event is to be 805 considered a draft. The server will not send any scheduling 806 messages to participants or send push notifications for alerts. 807 This may only be set to true upon creation. Once set to false, 808 the value cannot be updated to true. This property MUST NOT 809 appear in "recurrenceOverrides". 811 * *utcStart*: UTCDate For simple clients that do not or cannot 812 implement time zone support. Clients should only use this if also 813 asking the server to expand recurrences, as you cannot accurately 814 expand a recurrence without the original time zone. 816 This property is calculated at fetch time by the server. Time 817 zones are political and they can and do change at any time. 818 Fetching exactly the same property again may return a different 819 results if the time zone data has been updated on the server. 820 Time zone data changes are not considered "updates" to the event. 822 If set, server will convert to the event's current time zone using 823 its current time zone data and store the local time. 825 This is not included by default and must be requested explicitly. 827 Floating events (events without a time zone) will be interpreted 828 as per the time zone given as a CalendarEvent/get argument. 830 Note that it is not possible to accurately calculate the expansion 831 of recurrence rules or recurrence overrides with the utcStart 832 property rather than the local start time. Even simple 833 recurrences such as "repeat weekly" may cross a daylight-savings 834 boundary and end up at a different UTC time. Clients that wish to 835 use "utcStart" are RECOMMENDED to request the server expand 836 recurrences (see Section XXX). 838 * *utcEnd*: UTCDate The server calculates the end time in UTC from 839 the start/timeZone/duration properties of the event. This is not 840 included by default and must be requested explicitly. Like 841 utcStart, this is calculated at fetch time if requested and may 842 change due to time zone data changes. Floating events will be 843 interpreted as per the time zone given as a CalendarEvent/get 844 argument. 846 CalendarEvent objects MUST NOT have a "method" property as this is 847 only used when representing iTIP [RFC5546] scheduling messages, not 848 events in a data store. 850 5.1. Additional JSCalendar properties 852 This document defines three new JSCalendar properties. 854 5.1.1. mayInviteSelf 856 Type: Boolean (default: false) 858 If true, any user may add themselves to the event as a participant 859 with the "attendee" role. This property MUST NOT be altered in the 860 recurrenceOverrides; it may only be set on the base object. 862 This indicates the owner will accept "party crasher" RSVPs via iTIP, 863 subject to any other domain-specific restrictions, and users may add 864 themselves to the event via JMAP as long as they have the mayRSVP 865 permission for the calendar. 867 5.1.2. mayInviteOthers 869 Type: Boolean (default: false) 871 If true, any current participant with the "attendee" role may add new 872 participants with the "attendee" role to the event. This property 873 MUST NOT be altered in the recurrenceOverrides; it may only be set on 874 the base object. 876 The mayRSVP permission for the calendar is also required in 877 conjunction with this event property for users to be allowed to make 878 this change via JMAP. 880 5.1.3. hideAttendees 882 Type: Boolean (default: false) 884 If true, only the owners of the event may see the full set of 885 participants. Other sharees of the event may only see the owners and 886 themselves. This property MUST NOT be altered in the 887 recurrenceOverrides; it may only be set on the base object. 889 5.2. Attachments 891 The Link object, as defined in [RFC8984] Section 4.2.7, with a "rel" 892 property equal to "enclosure" is used to represent attachments. 893 Instead of mandating an "href" property, clients may set a "blobId" 894 property instead to reference a blob of binary data in the account, 895 as per [RFC8620] Section 6. 897 The server MUST translate this to an embedded data: URL [RFC2397] 898 when sending the event to a system that cannot access the blob. 899 Servers that support CalDAV access to the same data are recommended 900 to expose these files as managed attachments [?@RFC8607]. 902 5.3. Per-user properties 904 In shared calendars where the account's "shareesActAs" capability is 905 "self", the following properties MUST be stored per-user: 907 * keywords 908 * color 909 * freeBusyStatus 910 * useDefaultAlerts 911 * alerts 913 The user may also modify these properties on a per-occurrence basis 914 for recurring events; again, these MUST be stored per-user. 916 When writing only per-user properties, the "updated" property MUST 917 also be stored just for that user if set. When fetching the 918 "updated" property, the value to return is whichever is later of the 919 per-user updated time or the updated time of the base event. 921 5.4. Recurring events 923 Events may recur, in which case they represent multiple occurrences 924 or instances. The data store will either contain a single base 925 event, containing a recurrence rule and/or recurrence overrides; or, 926 a set of individual instances (when invited to specific occurrences 927 only). 929 The client may ask the server to expand recurrences within a specific 930 time range in "CalendarEvent/query". This will generate synthetic 931 ids representing individual instances in the requested time range. 932 The client can fetch and update the objects using these ids and the 933 server will make the appropriate changes to the base event. 934 Synthetic ids do not appear in "CalendarEvent/changes" responses; 935 only the ids of events as actually stored on the server. 937 If the user is invited to specific instances then later added to the 938 base event, "CalendarEvent/changes" will show the ids of all the 939 individual instances being destroyed and the id for the base event 940 being created. 942 5.5. Updating for "this-and-future" 944 When editing a recurring event, you can either update the base event 945 (affecting all instances unless overriden) or update an override for 946 a specific occurrence. To update all occurrences from a specific 947 point onwards, there are therefore two options: split the event, or 948 update the base event and override all occurrences before the split 949 point back to their original values. 951 5.5.1. Splitting an event 953 If the event is not scheduled (has no participants), the simplest 954 thing to do is to duplicate the event, modifying the recurrence rules 955 of the original so it finishes before the split point, and the 956 duplicate so it starts at the split point. As per JSCalendar 957 [RFC8984] Section 4.1.3, a "next" and "first" relation MUST be set on 958 the new objects respectively. 960 Splitting an event however is problematic in the case of a scheduled 961 event, because the iTIP messages generated make it appear like two 962 unrelated changes, which can be confusing. 964 5.5.2. Updating the base event and overriding previous 966 For scheduled events, a better approach is to avoid splitting and 967 instead update the base event with the new property value for "this 968 and future", then create overrides for all occurrences before the 969 split point to restore the property to its previous value. Indeed, 970 this may be the only option the user has permission to do if not an 971 owner of the event. 973 Clients may choose to skip creating the overrides if the old data is 974 not important, for example if the "alerts" property is being updated, 975 it is probably not important to create overrides for events in the 976 past with the alerts that have already fired. 978 5.6. CalendarEvent/get 980 This is a standard "/get" method as described in [RFC8620], 981 Section 5.1, with three extra arguments: 983 * *recurrenceOverridesBefore*: UTCDate|null If given, only 984 recurrence overrides with a recurrence id before this date (when 985 translated into UTC) will be returned. 986 * *recurrenceOverridesAfter*: UTCDate|null If given, only recurrence 987 overrides with a recurrence id on or after this date (when 988 translated into UTC) will be returned. 989 * *reduceParticipants*: Boolean (default: false) If true, only 990 participants with the "owner" role or corresponding to the user's 991 participant identities will be returned in the "participants" 992 property of the base event and any recurrence overrides. If 993 false, all participants will be returned. 994 * *timeZone*: String (default "Etc/UTC") The time zone to use when 995 calculating the utcStart/utcEnd property of floating events. This 996 argument has no effect if those properties are not requested. 998 A CalendarEvent object is a JSEvent object so may have arbitrary 999 properties. If the client makes a "CalendarEvent/get" call with a 1000 null or omitted "properties" argument, all properties defined on the 1001 JSEvent object in the store are returned, along with the "id", 1002 "calendarIds", and "isDraft" properties. The "utcStart" and "utcEnd" 1003 computed properties are only returned if explicitly requested. If 1004 either are requested, the "recurrenceOverrides" property MUST NOT be 1005 requested (recurrence overrides cannot be interpreted accurately with 1006 just the UTC times). 1008 If specific properties are requested from the JSEvent and the 1009 property is not present on the object in the server's store, the 1010 server SHOULD return the default value if known for that property. 1012 A requested id may represent a server-expanded single instance of a 1013 recurring event if the client asked the server to expand recurrences 1014 in "CalendarEvent/query". In such a case, the server will resolve 1015 any overrides and set the appropriate "start" and "recurrenceId" 1016 properties on the CalendarEvent object returned to the client. The 1017 "recurrenceRule" and "recurrenceOverrides" properties MUST be 1018 returned as null if requested for such an event. 1020 An event with the same uid/recurrenceId may appear in different 1021 accounts. Clients may coalesce the view of such events, but must be 1022 aware that the data may be different in the different accounts due to 1023 per-user properties, difference in permissions etc. 1025 The "privacy" property of a JSEvent object allows the owner to 1026 override how sharees of the calendar see the event. If this is set 1027 to "private", when a sharee fetches the event the server MUST only 1028 return the basic time and metadata properties of the JSEvent object 1029 as specified in [RFC8984], Section 4.4.3. If set to "secret", the 1030 server MUST behave as though the event does not exist for all users 1031 other than the owner. 1033 This "hideAttendees" property of a JSEvent object allows the owner to 1034 reduce the visibility of sharees into the set of participants. If 1035 this is true, when a non-owner sharee fetches the event, the server 1036 MUST only return participants with the "owner" role or corresponding 1037 to the user's participant identities. 1039 5.7. CalendarEvent/changes 1041 This is a standard "/changes" method as described in [RFC8620], 1042 Section 5.2. 1044 Synthetic ids generated by the server expanding recurrences in 1045 "CalendarEvent/query" do not appear in "CalendarEvent/changes" 1046 responses; only the ids of events as actually stored on the server. 1048 5.8. CalendarEvent/set 1050 This is a standard "/set" method as described in [RFC8620], 1051 Section 5.3, with the following extra argument: 1053 * *sendSchedulingMessages*: Boolean (default: false) If true then 1054 any changes to scheduled events will be sent to all the 1055 participants (if the user is an owner of the event) or back to the 1056 owners (otherwise). If false, the changes only affect this 1057 account and no scheduling messages will be sent. 1059 An id may represent a server-expanded single instance of a recurring 1060 event if the client asked the server to expand recurrences in 1061 "CalendarEvent/query". When the synthetic id for such an instance is 1062 given, the server MUST process an update as an update to the 1063 recurrence override for that instance on the base event, and a 1064 destroy as removing just that instance. 1066 Clients MUST NOT send an update/destroy to both the base event and a 1067 synthetic instance in a single "/set" request; the result of this is 1068 undefined. Note however, a client may replace a series of explicit 1069 instances (each with the same uid but a different recurrenceId 1070 property) with the base event (same uid, no recurrenceId) in a single 1071 "/set" call. (So the /set will destroy the existing instances and 1072 create the new base event.) This will happen when someone is 1073 initially invited to a specific instance or instances of a recurring 1074 event, then later invited to the whole series. 1076 Servers MUST enforce the user's permissions as returned in the 1077 "myRights" property of the Calendar objects and reject changes with a 1078 forbidden SetError if not allowed. 1080 The "privacy" property of a JSEvent object allows the owner to 1081 override how sharees of the calendar see the event. If this is set 1082 to "private", a sharee may not delete or update the event (even if 1083 only modifying per-user properties); any attempt to modify such an 1084 event MUST be rejected with a forbidden SetError. If set to 1085 "secret", the server MUST behave as though the event does not exist 1086 for all users other than the owner. 1088 The "privacy" property MUST NOT be set to anything other than 1089 "public" (the default) for events in a calendar that does not belong 1090 to the user (e.g. a shared team calendar). The server MUST reject 1091 this with an invalidProperties SetError. 1093 If omitted on create, the server MUST set the following properties to 1094 an appropriate value: 1096 * @type 1097 * uid 1098 * created 1100 If (and only if) the server is the source of the event (see 1101 Section XXX), the "updated" property MUST be set to the current time 1102 by the server whenever an event is created or updated. If the client 1103 tries to set a value for this property it is not an error, but it 1104 MUST be overridden and replaced with the server's time. If the event 1105 is being created and the overridden "updated" time is now earlier 1106 than a client-supplied "created" time, the "created" time MUST also 1107 be overridden to the server's time. If the server is not the source 1108 of the event it MUST NOT automatically set an "updated" time, as this 1109 can break correct processing of iTIP messages. 1111 When updating an event, if all of: 1113 * a property has been changed other than "calendarIds", "isDraft" or 1114 a per-user property (see Section XXX); and 1115 * the server is the source of the event (see Section XXX); and 1116 * the "sequence" property is not explicitly set in the update, or 1117 the given value is less than or equal to the current "sequence" 1118 value on the server; 1120 then the server MUST increment the "sequence" value by one. 1122 The "created" property MUST NOT be updated after creation. The 1123 "method" property MUST NOT be set. Any attempt to do these is 1124 rejected with a standard invalidProperties SetError. 1126 If "utcStart" is set, this is translated into a "start" property 1127 using the server's current time zone information. It MUST NOT be set 1128 in addition to a "start" property and it cannot be set inside 1129 "recurrenceOverrides"; this MUST be rejected with an 1130 invalidProperties SetError. 1132 Similarly, the "utcEnd" property is translated into a "duration" 1133 property if set. It MUST NOT be set in addition to a "duration" 1134 property and it cannot be set inside "recurrenceOverrides"; this MUST 1135 be rejected with an invalidProperties SetError. 1137 The server does not automatically reset the "partipationStatus" or 1138 "expectReply" properties of a Participant when changing other event 1139 details. Clients should either be intelligent about whether the 1140 change necessitates resending RSVP requests, or ask the user whether 1141 to send them. 1143 The server MAY enforce that all events have an owner, for example in 1144 team calendars. If the user tries to create an event without 1145 participants in such a calendar, the server MUST automatically add a 1146 participant with the "owner" role corresponding to one of the user's 1147 ParticipantIdentities (see Section XXX). 1149 When creating an event with participants, or adding participants to 1150 an event that previously did not have participants, the server MUST 1151 set the "replyTo" property of the event if not present. Clients 1152 SHOULD NOT set the replyTo property for events when the user adds 1153 participants; the server is better positioned to add all the methods 1154 it supports to receive replies. 1156 5.8.1. Patching 1158 The JMAP "/set" method allows you to update an object by sending a 1159 patch, rather than having to supply the whole object. When doing so, 1160 care must be taken if updating a property of a CalendarEvent where 1161 the value is itself a PatchObject, e.g. inside "localizations" or 1162 "recurrenceOverrides". In particular, you cannot add a property with 1163 value null to the CalendarEvent using a direct patch on that 1164 property, as this is interpreted instead as a patch to remove the 1165 property. This is more easily understood with an example. Suppose 1166 you have a CalendarEvent object like so: 1168 { 1169 "id": "123", 1170 "title": "FooBar team meeting", 1171 "start": "2018-01-08T09:00:00", 1172 "recurrenceRules": [{ 1173 "@type": "RecurrenceRule", 1174 "frequency": "weekly" 1175 }], 1176 "replyTo": { 1177 "imip": "mailto:6489-4f14-a57f-c1@schedule.example.com" 1178 }, 1179 "participants": { 1180 "dG9tQGZvb2Jhci5xlLmNvbQ": { 1181 "@type": "Participant", 1182 "name": "Tom", 1183 "email": "tom@foobar.example.com", 1184 "sendTo": { 1185 "imip": "mailto:6489-4f14-a57f-c1@calendar.example.com" 1186 }, 1187 "participationStatus": "accepted", 1188 "roles": { 1189 "attendee": true 1190 } 1191 }, 1192 "em9lQGZvb2GFtcGxlLmNvbQ": { 1193 "@type": "Participant", 1194 "name": "Zoe", 1195 "email": "zoe@foobar.example.com", 1196 "sendTo": { 1197 "imip": "mailto:zoe@foobar.example.com" 1198 }, 1199 "participationStatus": "accepted", 1200 "roles": { 1201 "owner": true, 1202 "attendee": true, 1203 "chair": true 1204 } 1205 }, 1206 "recurrenceOverrides": { 1207 "2018-03-08T09:00:00": { 1208 "start": "2018-03-08T10:00:00", 1209 "participants/dG9tQGZvb2Jhci5xlLmNvbQ/participationStatus": 1210 "declined" 1211 } 1212 } 1213 } 1214 } 1215 In this example, Tom is normally going to the weekly meeting but has 1216 declined the occurrence on 2018-03-08, which starts an hour later 1217 than normal. Now, if Zoe too were to decline that meeting, she could 1218 update the event by just sending a patch like so: 1220 [[ "CalendarEvent/set", { 1221 "accountId": "ue150411c", 1222 "update": { 1223 "123": { 1224 "recurrenceOverrides/2018-03-08T09:00:00/ 1225 participants~1em9lQGZvb2GFtcGxlLmNvbQ~1participationStatus": 1226 "declined" 1227 } 1228 } 1229 }, "0" ]] 1231 This patches the "2018-03-08T09:00:00" PatchObject in 1232 recurrenceOverrides so that it ends up like this: 1234 "recurrenceOverrides": { 1235 "2018-03-08T09:00:00": { 1236 "start": "2018-03-08T10:00:00", 1237 "participants/dG9tQGZvb2Jhci5xlLmNvbQ/participationStatus": 1238 "declined", 1239 "participants/em9lQGZvb2GFtcGxlLmNvbQ/participationStatus": 1240 "declined" 1241 } 1242 } 1244 Now if Tom were to change his mind and remove his declined status 1245 override (thus meaning he is attending, as inherited from the top- 1246 level event), he might remove his patch from the overrides like so: 1248 [[ "CalendarEvent/set", { 1249 "accountId": "ue150411c", 1250 "update": { 1251 "123": { 1252 "recurrenceOverrides/2018-03-08T09:00:00/ 1253 participants~1dG9tQGZvb2Jhci5xlLmNvbQ~1participationStatus": null 1254 } 1255 } 1256 }, "0" ]] 1258 However, if you instead want to remove Tom from this instance 1259 altogether, you could not send this patch: 1261 [[ "CalendarEvent/set", { 1262 "accountId": "ue150411c", 1263 "update": { 1264 "123": { 1265 "recurrenceOverrides/2018-03-08T09:00:00/ 1266 participants~1dG9tQGZvb2Jhci5xlLmNvbQ": null 1267 } 1268 } 1269 }, "0" ]] 1271 This would mean remove the "participants/dG9tQGZvb2Jhci5xlLmNvbQ" 1272 property at path "recurrenceOverrides" -> "2018-03-08T09:00:00" 1273 inside the object; but this doesn't exist. We actually we want to 1274 add this property and make it map to null. The client must instead 1275 send the full object that contains the property mapping to null, like 1276 so: 1278 [[ "CalendarEvent/set", { 1279 "accountId": "ue150411c", 1280 "update": { 1281 "123": { 1282 "recurrenceOverrides/2018-03-08T09:00:00": { 1283 "start": "2018-03-08T10:00:00", 1284 "participants/em9lQGZvb2GFtcGxlLmNvbQ/participationStatus": 1285 "declined" 1286 "participants/dG9tQGZvb2Jhci5xlLmNvbQ": null 1287 } 1288 } 1289 } 1290 }, "0" ]] 1292 5.8.2. Sending invitations and responses 1294 If "sendSchedulingMessages" is true, the server MUST send appropriate 1295 iTIP [RFC5546] scheduling messages after successfuly creating, 1296 updating or destroying a calendar event. 1298 When determining which scheduling messages to send, the server must 1299 first establish whether it is the _source_ of the event. The server 1300 is the source if it will receive messages sent to any of the methods 1301 specified in the "replyTo" property of the event. 1303 Messages are only sent to participants with a "scheduleAgent" 1304 property set to "server" or omitted. If the effective 1305 "scheduleAgent" property is changed: 1307 * to "server" from something else: send messages to this participant 1308 as though the event had just been created. 1310 * from "server" to something else: send messages to this participant 1311 as though the event had just been destroyed. 1312 * any other change: do not send any messages to this participant. 1314 The server may send the scheduling message via any of the methods 1315 defined on the sendTo property of a participant (if the server is the 1316 source) or the replyTo property of the event (otherwise) that it 1317 supports. If no supported methods are available, the server MUST 1318 reject the change with a noSupportedScheduleMethods SetError. 1320 If the server is the source of the event it MUST NOT send messages to 1321 any participant corresponding to a ParticipantIdentitity in that 1322 account (see Section XXX). 1324 If sending via iMIP [RFC6047], the server MAY choose to only send 1325 updates it deems "essential" to avoid flooding the recipient's email 1326 with changes they do not care about. For example, changes to the 1327 participationStatus of another participant, or changes to events 1328 solely in the past may be omitted. 1330 5.8.2.1. REQUEST 1332 When the server is the source for the event, a REQUEST message 1333 ([RFC5546], Section 3.2.2) is sent to all current participants if 1334 either: 1336 * The event is being created; or 1337 * Any non per-user property (see Section XXX) is updated on the 1338 event (including adding/removing participants), except if just 1339 modifying the recurrenceOverrides such that CANCEL messages are 1340 generated (see the next section). 1342 Note, if the only change is adding an additional instance (not 1343 generated by the event's recurrence rule) to the recurrenceOverrides, 1344 this MAY be handled via sending an ADD message ([RFC5546], 1345 Section 3.2.4) for the single instance rather than a REQUEST message 1346 for the base event. However, for interoperability reasons this is 1347 not recommended due to poor support in the wild for this type of 1348 message. 1350 The server MUST ensure participants are only sent information about 1351 recurrence instances they are added to when sending scheduling 1352 messages for recurring events. If the participant is not invited to 1353 the full recurring event but only individual instances, scheduling 1354 messages MUST be sent for just those expanded occurrences 1355 individually. If a participant is invited to a recurring event, but 1356 removed via a recurrence override from a particular instance, any 1357 scheduling messages to this participant MUST return the instance as 1358 "excluded" (if it matches a recurrence rule for the event) or omit 1359 the instance entirely (otherwise). 1361 If the event's "hideAttendees" property is set to true, the recipient 1362 MUST be the only attendee in the message; all others are omitted. 1364 5.8.2.2. CANCEL 1366 When the server is the source for the event, a CANCEL message 1367 ([RFC5546], Section 3.2.5) is sent if any of: 1369 * A participant is removed from either the base event or a single 1370 instance (the message is only sent to this participant; remaining 1371 participants will get a REQUEST, as described above). 1372 * The event is destroyed. 1373 * An exclusion is added to recurrenceOverrides to remove an instance 1374 generated by the event's recurrence rule. 1375 * An additional instance (not generated by the event's recurrence 1376 rule) is removed from the recurrenceOverrides. 1378 In each of the latter 3 cases, the message is sent to all 1379 participants. 1381 5.8.2.3. REPLY 1383 When the server is _not_ the source for the event, a REPLY message 1384 ([RFC5546], Section 3.2.3) is sent for every participant 1385 corresponding to one of the user's ParticipantIdentitities in the 1386 account if any of the following changes are made: 1388 * The "participationStatus" property of the participant is changed, 1389 either for the base event or a specific instance, to any value 1390 other than "needs-action". 1391 * The event is created and the participationStatus is not "needs- 1392 action". 1393 * The event is destroyed and the participationStatus was not "needs- 1394 action". 1396 If the participationStatus property is changed for just a single 1397 instance of the event (i.e., set in recurrenceOverrides), the REPLY 1398 message SHOULD be sent for just that recurrence id. 1400 5.9. CalendarEvent/copy 1402 This is a standard "/copy" method as described in [RFC8620], 1403 Section 5.4. 1405 5.10. CalendarEvent/query 1407 This is a standard "/query" method as described in [RFC8620], 1408 Section 5.5, with two extra arguments: 1410 * *expandRecurrences*: Boolean (default: false) If true, the server 1411 will expand any recurring event. If true, the filter MUST be just 1412 a FilterCondition (not a FilterOperator) and MUST include both a 1413 before and after property. This ensures the server is not asked 1414 to return an infinite number of results. 1415 * *timeZone*: String The time zone for before/after filter 1416 conditions (default: "Etc/UTC") 1418 If expandRecurrences is true, a separate id will be returned for each 1419 instance of a recurring event that matches the query. This synthetic 1420 id is opaque to the client, but allows the server to resolve the id + 1421 recurrence id for "/get" and "/set" operations. Otherwise, a single 1422 id will be returned for matching recurring events that represents the 1423 entire event. 1425 There is no necessary correspondence between the ids of different 1426 instances of the same expanded event. 1428 The following additional error may be returned instead of the 1429 "CalendarEvent/query" response: 1431 cannotCalculateOccurrences: the server cannot expand a recurrence 1432 required to return the results for this query. 1434 5.10.1. Filtering 1436 A *FilterCondition* object has the following properties: 1438 * *inCalendars*: Id[]|null A list of calendar ids. An event must be 1439 in ANY of these calendars to match the condition. 1440 * *after*: LocalDate|null The end of the event, or any recurrence of 1441 the event, in the time zone given as the timeZone argument, must 1442 be after this date to match the condition. 1444 * *before*: LocalDate|null The start of the event, or any recurrence 1445 of the event, in the time zone given as the timeZone argument, 1446 must be before this date to match the condition. 1447 * *text*: String|null Looks for the text in the _title_, 1448 _description_, _locations_ (matching name/description), 1449 _participants_ (matching name/email) and any other textual 1450 properties of the event or any recurrence of the event. 1451 * *title*: String|null Looks for the text in the _title_ property of 1452 the event, or the overridden _title_ property of a recurrence. 1453 * *description*: String|null Looks for the text in the _description_ 1454 property of the event, or the overridden _description_ property of 1455 a recurrence. 1456 * *location*: String|null Looks for the text in the _locations_ 1457 property of the event (matching name/description of a location), 1458 or the overridden _locations_ property of a recurrence. 1459 * *owner*: String|null Looks for the text in the name or email 1460 fields of a participant in the _participants_ property of the 1461 event, or the overridden _participants_ property of a recurrence, 1462 where the participant has a role of "owner". 1463 * *attendee*: String|null Looks for the text in the name or email 1464 fields of a participant in the _participants_ property of the 1465 event, or the overridden _participants_ property of a recurrence, 1466 where the participant has a role of "attendee". 1467 * *participationStatus*: Must match. If owner/attendee condition, 1468 status must be of that participant. Otherwise any. 1469 * *uid*: String The uid of the event is exactly the given string. 1471 If expandRecurrences is true, all conditions must match against the 1472 same instance of a recurring event for the instance to match. If 1473 expandRecurrences is false, all conditions must match, but they may 1474 each match any instance of the event. 1476 If zero properties are specified on the FilterCondition, the 1477 condition MUST always evaluate to true. If multiple properties are 1478 specified, ALL must apply for the condition to be true (it is 1479 equivalent to splitting the object into one-property conditions and 1480 making them all the child of an AND filter operator). 1482 The exact semantics for matching String fields is *deliberately not 1483 defined* to allow for flexibility in indexing implementation, subject 1484 to the following: 1486 * Text SHOULD be matched in a case-insensitive manner. 1487 * Text contained in either (but matched) single or double quotes 1488 SHOULD be treated as a *phrase search*, that is a match is 1489 required for that exact sequence of words, excluding the 1490 surrounding quotation marks. Use \", \' and \\ to match a literal 1491 ", ' and \ respectively in a phrase. 1493 * Outside of a phrase, white-space SHOULD be treated as dividing 1494 separate tokens that may be searched for separately in the event, 1495 but MUST all be present for the event to match the filter. 1496 * Tokens MAY be matched on a whole-word basis using stemming (so for 1497 example a text search for bus would match "buses" but not 1498 "business"). 1500 5.10.2. Sorting 1502 The following properties MUST be supported for sorting: 1504 * start 1505 * uid 1506 * recurrenceId 1508 The following properties SHOULD be supported for sorting: 1510 * created 1511 * updated 1513 5.11. CalendarEvent/queryChanges 1515 This is a standard "/queryChanges" method as described in [RFC8620], 1516 Section 5.6. 1518 5.12. Examples 1520 TODO: Add example of how to get event by uid: query uid=foo and 1521 backref. Return multiple with recurrenceId set (user invited to 1522 specific instances of recurring event). 1524 6. Alerts 1526 Alerts may be specified on events as described in [RFC8984], 1527 Section 4.5. 1529 Alerts MUST only be triggered for events in calendars where the user 1530 is subscribed and either the user owns the calendar or the calendar 1531 account's "shareesActAs" capability is "self". 1533 When an alert with an "email" action is triggered, the server MUST 1534 send an email to the user to notify them of the event. The contents 1535 of the email is implementation specific. Clients MUST NOT perform an 1536 action for these alerts. 1538 When an alert with a "display" action is triggered, clients SHOULD 1539 display an alert in a platform-appropriate manner to the user to 1540 remind them of the event. Clients with a full offline cache of 1541 events may choose to calculate when alerts should trigger locally. 1542 Alternatively, they can subscribe to push events from the server. 1544 6.1. Default alerts 1546 If the "useDefaultAlerts" property of an event is true, the alerts 1547 are taken from the "defaultAlertsWithTime" or 1548 "defaultAlertsWithoutTime" property of all Calendars the event is in, 1549 as described in Section XXX, rather than the "alerts" property of the 1550 CalendarEvent. 1552 When using default alerts, the "alerts" property of the event is 1553 ignored except for the following: 1555 * The "acknowledged" time for an alert is stored here when a default 1556 alert for the event is dismissed. The id of the alert MUST be the 1557 same as the id of the default alert in the calendar. See 1558 Section XXX on acknowledging alerts. 1559 * If an alert has a relatedTo property where the parent is the id of 1560 one of the calendar default alerts, it is processed as normal and 1561 not ignored. This is to support snoozing default alerts; see 1562 Section XXX. 1564 6.2. Acknowledging an alert 1566 To dismiss an alert, clients set the "acknowledged" property of the 1567 Alert object to the current date-time. If the alert was a calendar 1568 default, it may need to be added to the event at this point in order 1569 to acknowledge it. When other clients fetch the updated 1570 CalendarEvent they SHOULD automatically dismiss or suppress duplicate 1571 alerts (alerts with the same alert id that triggered on or before the 1572 "acknowledged" date-time) and alerts that have been removed from the 1573 event. 1575 Setting the "acknowledged" property MUST NOT create a new recurrence 1576 override. For a recurring calendar object, the "acknowledged" 1577 property of the parent object MUST be updated, unless the alert is 1578 already overridden in the "recurrenceOverrides" property. 1580 6.3. Snoozing an alert 1582 Users may wish to dismiss an alert temporarily and have it come back 1583 after a specific period of time. To do this, clients MUST: 1585 1. Acknowledge the alert as described in Section XXX. 1587 2. Add a new alert to the event with an AbsoluteTrigger for the 1588 date-time the alert has been snoozed until. Add a "relatedTo" 1589 property to the new alert, setting the "parent" relation to point 1590 to the original alert. This MUST NOT create a new recurrence 1591 override; it is added to the same "alerts" property that contains 1592 the alert that was acknowledged in step 1. 1594 When acknowledging a snoozed alert (i.e. one with a parent relatedTo 1595 pointing to the original alert), the client SHOULD delete the alert 1596 rather than setting the "acknowledged" property. 1598 6.4. Push events 1600 Servers that support the urn:ietf:params:jmap:calendars capability 1601 MUST support registering for the pseudo-type "CalendarAlert" in push 1602 subscriptions and event source connections, as described in 1603 [RFC8620], Sections 7.2 and 7.3. 1605 If requested, a CalendarAlert notification will be pushed whenever an 1606 alert is triggered for the user. For Event Source connections, this 1607 notification is pushed as an event called "calendarAlert". 1609 A *CalendarAlert* object has the following properties: 1611 * *@type*: String This MUST be the string "CalendarAlert". 1612 * *accountId*: String The account id for the calendar in which the 1613 alert triggered. 1614 * *calendarEventId*: String The CalendarEvent id for the alert that 1615 triggered. 1616 * *uid*: String The uid property of the CalendarEvent for the alert 1617 that triggered. 1618 * *recurrenceId*: String|null The recurrenceId for the instance of 1619 the event for which this alert is being triggered, or null if the 1620 event is not recurring. 1621 * *alertId*: String The id for the alert that triggered. 1623 7. Calendar Event Notifications 1625 The CalendarEventNotification data type records changes made by 1626 external entities to events in calendars the user is subscribed to. 1627 Notifications are stored in the same Account as the CalendarEvent 1628 that was changed. 1630 Notifications are only created by the server; users cannot create 1631 them directly. Clients SHOULD present the list of notifications to 1632 the user and allow them to dismiss them. To dismiss a notification 1633 you use a standard "/set" call to destroy it. 1635 The server SHOULD create a CalendarEventNotification whenever an 1636 event is added, updated or destroyed by another user or due to 1637 receiving an iTIP [RFC5546] or other scheduling message in a calendar 1638 this user is subscribed to. The server SHOULD NOT create 1639 notifications for events implicitly deleted due to the containing 1640 calendar being deleted. 1642 The CalendarEventNotification does not have any per-user data. A 1643 single instance may therefore be maintained on the server for all 1644 sharees of the notification. The server need only keep track of 1645 which users have yet to destroy the notification. 1647 7.1. Auto-deletion of Notifications 1649 The server MAY limit the maximum number of notifications it will 1650 store for a user. When the limit is reached, any new notification 1651 will cause the previously oldest notification to be automatically 1652 deleted. 1654 The server MAY coalesce events if appropriate, or remove events that 1655 it deems are no longer relevant or after a certain period of time. 1656 The server SHOULD automatically destroy a notification about an event 1657 if the user updates or destroys that event (e.g. if the user sends an 1658 RSVP for the event). 1660 7.2. Object Properties 1662 The *CalendarEventNotification* object has the following properties: 1664 * *id*: String The id of the CalendarEventNotification. 1665 * *created*: UTCDate The time this notification was created. 1666 * *changedBy*: Person Who made the change. 1667 - *name*: String The name of the person who made the change. 1668 - *email*: String The email of the person who made the change, or 1669 null if no email is available. 1670 - *principalId*: String|null The id of the calendar principal 1671 corresponding to the person who made the change, if any. This 1672 will be null if the change was due to receving an iTIP message. 1673 * *comment*: String|null Comment sent along with the change by the 1674 user that made it. (e.g. COMMENT property in an iTIP message). 1675 * *type*: String This MUST be one of 1676 - created 1677 - updated 1678 - destroyed 1679 * *calendarEventId*: String The id of the CalendarEvent that this 1680 notification is about. 1681 * *isDraft*: Boolean (created/updated only) Is this event a draft? 1682 * *event*: JSEvent The data before the change (if updated or 1683 destroyed), or the data after creation (if created). 1684 * *eventPatch*: PatchObject (updated only) A patch encoding the 1685 change between the data in the event property, and the data after 1686 the update. 1688 To reduce data, if the change only affects a single instance of a 1689 recurring event, the server MAY set the event and eventPatch 1690 properties for the instance; the calendarEventId MUST still be for 1691 the base event. 1693 7.3. CalendarEventNotification/get 1695 This is a standard "/get" method as described in [RFC8620], 1696 Section 5.1. 1698 7.4. CalendarEventNotification/changes 1700 This is a standard "/changes" method as described in [RFC8620], 1701 Section 5.2. 1703 7.5. CalendarEventNotification/set 1705 This is a standard "/changes" method as described in [RFC8620], 1706 Section 5.3. 1708 Only destroy is supported; any attempt to create/update MUST be 1709 rejected with a forbidden SetError. 1711 7.6. CalendarEventNotification/query 1713 This is a standard "/query" method as described in [RFC8620], 1714 Section 5.5. 1716 7.6.1. Filtering 1718 A *FilterCondition* object has the following properties: 1720 * *after*: UTCDate|null The creation date must be on or after this 1721 date to match the condition. 1722 * *before*: UTCDate|null The creation date must be before this date 1723 to match the condition. 1724 * *type*: String The type property must be the same to match the 1725 condition. 1726 * *calendarEventIds*: Id[]|null A list of event ids. The 1727 calendarEventId property of the notification must be in this list 1728 to match the condition. 1730 7.6.2. Sorting 1732 The "created" property MUST be supported for sorting. 1734 7.7. CalendarEventNotification/queryChanges 1736 This is a standard "/queryChanges" method as described in [RFC8620], 1737 Section 5.6. 1739 8. CalendarPreferences 1741 A CalendarPreferences object stores information about the principal's 1742 preferences and defaults. 1744 * *id*: Id (immutable; server-set) The id of the object. There is 1745 only ever one CalendarPreferences object, and its id is 1746 "singleton". 1748 * *defaultCalendarId*: Id|null The id of the principal's default 1749 calendar. If set, clients should default to this calendar when 1750 creating new events in this account, unless overridden by a local 1751 preference. When the principal is invited to an event, this is 1752 the calendar to which it will be added by the server. 1754 If null, no default is defined and clients/servers may choose any 1755 calendar. 1757 * *defaultParticipantIdentityId*: Id|null The default participant 1758 identity to use for the principal when adding participants to an 1759 event. If set, when the user adds an invitee to an event without 1760 an owner, the client should use this participant identity to add 1761 the principal as an owner participant of the event. 1763 If null, no default is defined and clients/servers may choose any 1764 participant identity. 1766 The following JMAP methods are supported. 1768 8.1. CalendarPreferences/get 1770 This is a standard "/get" method as described in [RFC8620], 1771 Section 5.1. 1773 There MUST only be exactly one CalendarPreferences object in an 1774 account. It MUST have the id "singleton". 1776 8.2. CalendarPreferences/set 1778 This is a standard "/set" method as described in [RFC8620], 1779 Section 5.3. There is always exactly one CalendarPreferences object 1780 in an account; it cannot be created or destroyed, only updated. 1782 9. Security Considerations 1784 All security considerations of JMAP [RFC8620] and JSCalendar 1785 [RFC8984] apply to this specification. Additional considerations 1786 specific to the data types and functionality introduced by this 1787 document are described in the following subsections. 1789 9.1. Privacy 1791 Calendars often contain the precise movements, activities, and 1792 contacts of people, and is therefore intensely private data. Privacy 1793 leaks can have real world consequences, and calendar servers and 1794 clients MUST be mindful of the need to keep all data secure. 1796 Servers MUST enforce the ACLs set on calendars to ensure only 1797 authorised data is shared. The additional restrictions specified by 1798 the "privacy" property of a JSEvent object (see [RFC8984] 1799 Section 4.4.3) MUST also be enforced. 1801 Users may have multiple Participant Identities that they use for 1802 areas of their life kept private from one another. Using one 1803 identity with an event MUST NOT leak the existence of any other 1804 identity. For example, sending an RSVP from identity 1805 worklife@example.com MUST NOT reveal anything about another identity 1806 present in the account such as privatelife@example.org. 1808 Severs SHOULD enforce that invitations sent to external systems are 1809 only transmitted via secure encrypted and signed connections to 1810 protect against eavesdropping and modification of data. 1812 9.2. Spoofing 1814 When receiving events and updates from external systems, it can be 1815 hard to verify that the identity of the author is who they claim to 1816 be. When receiving events via email, DKIM [RFC6376] and S/MIME 1817 [RFC8551] are two mechanisms that may be used to verify certain 1818 properties about the email data, which can be correlated with the 1819 event information. 1821 9.3. Denial-of-service 1823 There are many ways in which a calendar user can make a request 1824 liable to cause a calendar server to spend an inordinate amount of 1825 processing time. Care must be taken to limit resources allocated to 1826 any one user to ensure the system does not become unresponsive. The 1827 following subsections list particularly hazardous areas. 1829 9.3.1. Expanding Recurrences 1831 Recurrence rules can be crafted to occur as frequently as every 1832 second. Servers MUST be careful to not allow resources to be 1833 exhausted when expanding, and limit the number of expansions they 1834 will create. Equally, rules can be generated that never create any 1835 occurrences at all. Servers MUST be careful to limit the work spent 1836 iterating in search of the next occurrence. 1838 9.3.2. Firing alerts 1840 An alert firing for an event can cause a notification to be pused to 1841 the user's devices, or to send them an email. Servers MUST rate 1842 limit the number of alerts sent for any one user. The combination of 1843 recurring events with multiple alerts can in particular define 1844 unreasonably frequent alerts, leading to denial of service for either 1845 the server processing them or the user's devices receiving them. 1847 Similarly, clients generating alerts from the data on device must 1848 take the same precautions. 1850 The "email" alert type (see RFC8984, Section 4.5.2) causes an email 1851 to be sent when triggered. Clients MUST ignore this alert type; the 1852 email is sent only be the calendar server. There is no mechanism in 1853 JSCalendar to specify a particular email address: the server MUST 1854 only allow alerts to be sent to an address it has verified as 1855 belonging to the user to avoid this being used as a spamming vector. 1857 9.3.3. Load spikes 1859 Since most events are likely to start on the hour mark, a large spike 1860 of activity is often seen at these times, with particularly large 1861 spikes at certain common times in the time zone of the server's user 1862 base. In particular, a large number of alerts (across different 1863 users and events) will be triggered at the same time. Servers may 1864 mitigate this somewhat by adding jitter to the triggering of the 1865 alerts; it is RECOMMENDED to fire them slightly early rather than 1866 slightly late if needed to spread load. 1868 9.4. Spam 1870 Invitations received from an untrusted source may be spam. If this 1871 is added to the user's calendar automatically it can be very 1872 obtrusive, especially if it is a recurring event that now appears 1873 every day. Incoming invitations to events should be subject to spam 1874 scanning, and suspicious events should not be added to the calendar 1875 automatically. 1877 Servers should strip any alerts on invitations when adding to the 1878 user's calendar; the useDefaultAlerts property should be set instead 1879 to apply the user's preferences. 1881 Similarly, a malicious user may use a calendar system to send spam by 1882 inviting people to an event. Outbound iTIP should be subject to all 1883 the same controls used on outbound email systems, and rate limited as 1884 appropriate. A rate limit on the number of distinct recipients as 1885 well as overall messages is recommended. 1887 10. IANA Considerations 1889 10.1. JMAP Capability Registration for "calendars" 1891 IANA will register the "calendars" JMAP Capability as follows: 1893 Capability Name: urn:ietf:params:jmap:calendars 1895 Specification document: this document 1897 Intended use: common 1899 Change Controller: IETF 1901 Security and privacy considerations: this document, Section XXX 1903 10.2. JMAP Capability Registration for "calendars:preferences" 1905 IANA will register the "calendars:preferences" JMAP Capability as 1906 follows: 1908 Capability Name: urn:ietf:params:jmap:calendars:preferences 1910 Specification document: this document 1912 Intended use: common 1914 Change Controller: IETF 1915 Security and privacy considerations: this document, Section XXX 1917 10.3. JMAP Capability Registration for "principals:availability" 1919 IANA will register the "principals:availability" JMAP Capability as 1920 follows: 1922 Capability Name: urn:ietf:params:jmap:principals:availability 1924 Specification document: this document 1926 Intended use: common 1928 Change Controller: IETF 1930 Security and privacy considerations: this document, Section XXX 1932 10.4. JSCalendar Property Registrations 1934 IANA will register the following additional properties in the 1935 JSCalendar Properties Registry. 1937 10.4.1. id 1939 Property Name: id 1941 Property Type: Id 1943 Property Context: JSEvent, JSTask 1945 Intended Use: Reserved 1947 10.4.2. calendarIds 1949 Property Name: calendarIds 1951 Property Type: Id[Boolean] 1953 Property Context: JSEvent, JSTask 1955 Intended Use: Reserved 1957 10.4.3. isDraft 1959 Property Name: isDraft 1961 Property Type: Boolean 1962 Property Context: JSEvent, JSTask 1964 Intended Use: Reserved 1966 10.4.4. utcStart 1968 Property Name: utcStart 1970 Property Type: UTCDateTime 1972 Property Context: JSEvent, JSTask 1974 Intended Use: Reserved 1976 10.4.5. utcEnd 1978 Property Name: utcEnd 1980 Property Type: UTCDateTime 1982 Property Context: JSEvent, JSTask 1984 Intended Use: Reserved 1986 10.4.6. mayInviteSelf 1988 Property Name: mayInviteSelf 1990 Property Type: Boolean (default: false) 1992 Property Context: JSEvent, JSTask 1994 Reference: This document, Section XXX. 1996 Intended Use: Common 1998 10.4.7. mayInviteOthers 2000 Property Name: mayInviteOthers 2002 Property Type: Boolean (default: false) 2004 Property Context: JSEvent, JSTask 2006 Reference: This document, Section XXX. 2008 Intended Use: Common 2010 10.4.8. hideAttendees 2012 Property Name: hideAttendees 2014 Property Type: Boolean (default: false) 2016 Property Context: JSEvent, JSTask 2018 Reference: This document, Section XXX. 2020 Intended Use: Common 2022 11. Normative References 2024 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2025 Requirement Levels", BCP 14, RFC 2119, 2026 DOI 10.17487/RFC2119, March 1997, 2027 . 2029 [RFC2397] Masinter, L., "The "data" URL scheme", RFC 2397, 2030 DOI 10.17487/RFC2397, August 1998, 2031 . 2033 [RFC6376] Crocker, D., Ed., Hansen, T., Ed., and M. Kucherawy, Ed., 2034 "DomainKeys Identified Mail (DKIM) Signatures", STD 76, 2035 RFC 6376, DOI 10.17487/RFC6376, September 2011, 2036 . 2038 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2039 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2040 May 2017, . 2042 [RFC8551] Schaad, J., Ramsdell, B., and S. Turner, "Secure/ 2043 Multipurpose Internet Mail Extensions (S/MIME) Version 4.0 2044 Message Specification", RFC 8551, DOI 10.17487/RFC8551, 2045 April 2019, . 2047 [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application 2048 Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July 2049 2019, . 2051 [RFC8984] Jenkins, N. and R. Stepanek, "JSCalendar: A JSON 2052 Representation of Calendar Data", RFC 8984, 2053 DOI 10.17487/RFC8984, July 2021, 2054 . 2056 12. Informative References 2058 [RFC4791] Daboo, C., Desruisseaux, B., and L. Dusseault, 2059 "Calendaring Extensions to WebDAV (CalDAV)", RFC 4791, 2060 DOI 10.17487/RFC4791, March 2007, 2061 . 2063 [RFC5546] Daboo, C., Ed., "iCalendar Transport-Independent 2064 Interoperability Protocol (iTIP)", RFC 5546, 2065 DOI 10.17487/RFC5546, December 2009, 2066 . 2068 [RFC6047] Melnikov, A., Ed., "iCalendar Message-Based 2069 Interoperability Protocol (iMIP)", RFC 6047, 2070 DOI 10.17487/RFC6047, December 2010, 2071 . 2073 Authors' Addresses 2075 Neil Jenkins (editor) 2076 Fastmail 2077 PO Box 234, Collins St West 2078 Melbourne VIC 8007 2079 Australia 2080 Email: neilj@fastmailteam.com 2081 URI: https://www.fastmail.com 2083 Michael Douglass (editor) 2084 Spherical Cow Group 2085 226 3rd Street 2086 Troy, NY 12180 2087 United States of America 2088 Email: mdouglass@sphericalcowgroup.com 2089 URI: http://sphericalcowgroup.com