<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc SYSTEM 'rfc2629.dtd' []>
<rfc ipr="trust200902" category="std" docName="draft-jenkins-jmapcalendars-00">
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<?rfc private=""?>
<?rfc topblock="yes"?>
<?rfc comments="no"?>
<front>
<title abbrev="JMAP Calendars">JMAP for Calendars</title>

<author initials="N.M." surname="Jenkins" fullname="Neil Jenkins">
<organization>FastMail</organization>
<address>
<postal>
<street>PO Box 234, Collins St West</street>
<city>Melbourne</city>
<code>VIC 8007</code>
<country>Australia</country>
<region></region>
</postal>
<phone></phone>
<email>neilj@fastmailteam.com</email>
<uri>https://www.fastmail.com</uri>
</address>
</author>
<date year="2019" month="March" day="26"/>

<area>Applications</area>
<workgroup>JMAP</workgroup>
<keyword>JMAP</keyword>
<keyword>JSON</keyword>
<keyword>calendars</keyword>


<abstract>
<t>This document specifies a data model for synchronising calendar data with a server using JMAP.
</t>
</abstract>


</front>

<middle>

<section anchor="introduction" title="Introduction">
<t>JMAP (<xref target="I-D.ietf-jmap-core"/> – JSON Meta Application Protocol) is a generic protocol for synchronising data, such as mail, calendars or contacts, between a client and a server. It is optimised for mobile and web environments, and aims to provide a consistent interface to different data types.
</t>
<t>This specification defines a data model for synchronising calendar data between a client and a server using JMAP.
</t>

<section anchor="notational-conventions" title="Notational conventions">
<t>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.
</t>
<t>Type signatures, examples and property descriptions in this document follow the conventions established in section 1.1 of <xref target="I-D.ietf-jmap-core"/>.
</t>
<t>Object properties may also have a set of attributes defined along with the type
signature. These have the following meanings:
</t>
<t>
<list style="symbols">
<t><spanx style="strong">server-set</spanx>: Only the server can set the value for this property. The
client MUST NOT send this property when creating a new object of this type.</t>
<t><spanx style="strong">immutable</spanx>: The value MUST NOT change after the object is created.</t>
<t><spanx style="strong">default</spanx>: (This is followed by a JSON value). The value that will be used
for this property if it is omitted in an argument, or when creating a new object of this type.</t>
</list>
</t>
<t>Data types defined in the core specification are used in this document.
</t>
</section>

<section anchor="the-date-datatypes" title="The Date datatypes">
<t>Where <spanx style="verb">LocalDate</spanx> is given as a type, it means a string in the same format as <spanx style="verb">Date</spanx>, but with the <spanx style="emph">time-offset</spanx> omitted from the end. The interpretation in absolute time depends upon the time zone for the event, which may not be a fixed offset (for example when daylight saving time occurs). For example, <spanx style="verb">"2014-10-30T14:12:00"</spanx>.
</t>
</section>

<section anchor="terminology" title="Terminology">
<t>The same terminology is used in this document as in the core JMAP specification.
</t>
</section>

<section anchor="addition-to-the-capabilities-object" title="Addition to the capabilities object">
<t>The capabilities object is returned as part of the standard JMAP Session object; see the JMAP spec. Servers supporting <spanx style="emph">this</spanx> specification MUST add a property called <spanx style="verb">urn:ietf:params:jmap:calendars</spanx> to the capabilities object.
</t>
<t>The value of this property is an empty object in both the JMAP session <spanx style="emph">capabilities</spanx> property and an account's <spanx style="emph">accountCapabilities</spanx> property.
</t>
</section>
</section>

<section anchor="calendars" title="Calendars">
<t>A Calendar is a named collection of events. All events are associated with one, and only one, calendar.
</t>
<t>A <spanx style="strong">Calendar</spanx> object has the following properties:
</t>
<t>
<list style="symbols">
<t><spanx style="strong">id</spanx>: <spanx style="verb">Id</spanx> (immutable; server-set)
The id of the calendar.</t>
<t><spanx style="strong">name</spanx>: <spanx style="verb">String</spanx>
The user-visible name of the calendar. This may be any UTF-8 string of at least 1 character in length and maximum 255 octets in size.</t>
<t><spanx style="strong">color</spanx>: <spanx style="verb">String</spanx>
Any valid CSS color value. The color to be used when displaying events associated with the calendar. The color SHOULD have sufficient contrast to be used as text on a white background.</t>
<t><spanx style="strong">sortOrder</spanx>: <spanx style="verb">UnsignedInt</spanx> (default: 0)
Defines the sort order of calendars when presented in the client's UI, so it is
consistent between devices. The number MUST be an integer in the range
0 &lt;= sortOrder &lt; 2^31.</t>
</list>
</t>
<t>A calendar with a lower order should be displayed before a calendar with
  a higher order in any list of calendars in the client's UI. Calendars with
  equal order should be sorted in alphabetical order by name. The sorting
  should take into locale-specific character order convention.
- <spanx style="strong">isVisible</spanx>: <spanx style="verb">Boolean</spanx> (default: true)
  Should the calendar's events be displayed to the user at the moment?
- <spanx style="strong">mayReadFreeBusy</spanx>: <spanx style="verb">Boolean</spanx> (server-set)
  The user may read the free-busy information for this calendar. In JMAP
  terms, this means the user may use this calendar as part of a filter in a
  <spanx style="emph">CalendarEvent/query</spanx> call, however unless <spanx style="verb">mayRead == true</spanx>, the events
  returned for this calendar will only contain free-busy information, and be stripped of any other data.
  This property MUST be <spanx style="verb">true</spanx> if <spanx style="emph">mayRead</spanx> is <spanx style="verb">true</spanx>.
- <spanx style="strong">mayReadItems</spanx>: <spanx style="verb">Boolean</spanx> (server-set)
  The user may fetch the events in this calendar. In JMAP terms, this means
  the user may use this calendar as part of a filter in a
  <spanx style="emph">CalendarEvent/query</spanx> call
- <spanx style="strong">mayAddItems</spanx>: <spanx style="verb">Boolean</spanx> (server-set)
  The user may add events to this calendar. In JMAP terms, this means the
  user may call <spanx style="emph">CalendarEvent/set</spanx> to create new events in this calendar or
  move existing events into this calendar from another calendar.
  This property MUST be <spanx style="verb">false</spanx> if the account to which this calendar belongs
  has the <spanx style="emph">isReadOnly</spanx> property set to <spanx style="verb">true</spanx>.
- <spanx style="strong">mayModifyItems</spanx>: <spanx style="verb">Boolean</spanx> (server-set)
  The user may edit events in this calendar by calling <spanx style="emph">CalendarEvent/set</spanx> with
  the <spanx style="emph">update</spanx> argument referencing events in this collection.
  This property MUST be <spanx style="verb">false</spanx> if the account to which this calendar belongs
  has the <spanx style="emph">isReadOnly</spanx> property set to <spanx style="verb">true</spanx>.
- <spanx style="strong">mayRemoveItems</spanx>: <spanx style="verb">Boolean</spanx> (server-set)
  The user may remove events from this calendar by calling <spanx style="emph">CalendarEvent/set</spanx>
  with the <spanx style="emph">destroy</spanx> argument referencing events in this collection, or by
  updating their <spanx style="emph">calendarId</spanx> property to a different calendar.
  This property MUST be <spanx style="verb">false</spanx> if the account to which this calendar belongs
  has the <spanx style="emph">isReadOnly</spanx> property set to <spanx style="verb">true</spanx>.
- <spanx style="strong">mayRename</spanx>: <spanx style="verb">Boolean</spanx> (server-set)
  The user may rename the calendar.
  This property MUST be <spanx style="verb">false</spanx> if the account to which this calendar belongs
  has the <spanx style="emph">isReadOnly</spanx> property set to <spanx style="verb">true</spanx>.
- <spanx style="strong">mayDelete</spanx>: <spanx style="verb">Boolean</spanx> (server-set)
  The user may delete the calendar itself.
  This property MUST be <spanx style="verb">false</spanx> if the account to which this calendar belongs
  has the <spanx style="emph">isReadOnly</spanx> property set to <spanx style="verb">true</spanx>.
</t>

<section anchor="calendarget" title="Calendar/get">
<t>Standard &quot;/get&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.1. The <spanx style="emph">ids</spanx> argument may be <spanx style="verb">null</spanx> to fetch all at once.
</t>
</section>

<section anchor="calendarchanges" title="Calendar/changes">
<t>Standard &quot;/changes&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.2.
</t>
</section>

<section anchor="calendarset" title="Calendar/set">
<t>Standard &quot;/set&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.3.
</t>
<t>A calendar MAY be deleted that is currently associated with one or more events. In this case, the events belonging to this calendar MUST also be deleted. Conceptually, this MUST happen prior to the calendar itself being deleted, and MUST generate a <spanx style="strong">push</spanx> event that modifies the state of the <spanx style="emph">CalendarEvent</spanx> type for the account.
</t>
</section>
</section>

<section anchor="calendar-events" title="Calendar events">
<t>A <spanx style="strong">CalendarEvent</spanx> object contains information about an event, or recurring series of events, that takes place at a particular time. It is a JSEvent object, as defined in <xref target="I-D.ietf-calext-jscalendar"/>, with the following additional properties:
</t>
<t>
<list style="symbols">
<t><spanx style="strong">id</spanx>: <spanx style="verb">Id</spanx>
The id of the event. This property is immutable.</t>
<t><spanx style="strong">calendarId</spanx>: <spanx style="verb">Id</spanx>
The id of the calendar this event belongs to.</t>
<t><spanx style="strong">participantId</spanx>: <spanx style="verb">Id|null</spanx>
The id of the participant in the <spanx style="emph">participants</spanx> object which corresponds to the account this event is in.</t>
</list>
</t>

<section anchor="calendareventget" title="CalendarEvent/get">
<t>Standard &quot;/get&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.1.
</t>
</section>

<section anchor="calendareventchanges" title="CalendarEvent/changes">
<t>Standard &quot;/changes&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.2
</t>
</section>

<section anchor="calendareventset" title="CalendarEvent/set">
<t>Standard &quot;/set&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.3.
</t>
<t>When an event is created, updated or destroyed, the server MUST also ensure the following:
</t>
<t>
<list style="symbols">
<t>Any alerts are scheduled/cancelled correctly.</t>
<t>If there is a <spanx style="emph">participantId</spanx>, and the corresponding participant has a <spanx style="emph">role</spanx>
of <spanx style="verb">owner</spanx>:
<list style="symbols">
<t>If an event is created/updated: send a REQUEST iMIP email with the event as
an ICS attachment to all participants that are not &quot;you&quot;.</t>
<t>When an event is destroyed, if it is in the future, then email all
participants other than you the appropriate iMIP email to inform them that the event has been cancelled. If it is in the past, the server SHOULD NOT send a message.</t>
</list></t>
<t>If there is a <spanx style="emph">participantId</spanx>, and the corresponding participant does not have a <spanx style="emph">role</spanx> of <spanx style="verb">owner</spanx>, and the <spanx style="emph">scheduleStatus</spanx> is updated for this participant, send the appropriate iMIP email to the <spanx style="emph">replyTo</spanx> address.</t>
</list>
</t>
</section>

<section anchor="calendareventcopy" title="CalendarEvent/copy">
<t>Standard &quot;/copy&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.4.
</t>
</section>

<section anchor="calendareventquery" title="CalendarEvent/query">
<t>Standard &quot;/query&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.5.
</t>

<section anchor="filtering" title="Filtering">
<t>A <spanx style="strong">FilterCondition</spanx> object has the following properties:
</t>
<t>
<list style="symbols">
<t><spanx style="strong">inCalendars</spanx>: <spanx style="verb">Id[]|null</spanx>
A list of calendar ids. An event must be in ANY of these calendars to match the condition.</t>
<t><spanx style="strong">after</spanx>: <spanx style="verb">UTCDate|null</spanx>
The end of the event, or any recurrence of the event, in UTC time must be after this date to match the condition.</t>
<t><spanx style="strong">before</spanx>: <spanx style="verb">UTCDate|null</spanx>
The start of the event, or any recurrence of the event, in UTC time must be before this date to match the condition.</t>
<t><spanx style="strong">text</spanx>: <spanx style="verb">String|null</spanx>
Looks for the text in the <spanx style="emph">title</spanx>, <spanx style="emph">description</spanx>, <spanx style="emph">locations</spanx> (matching name/description), or <spanx style="emph">participants</spanx> (matching name/email) properties of the event or any recurrence of the event.</t>
<t><spanx style="strong">title</spanx>: <spanx style="verb">String|null</spanx>
Looks for the text in the <spanx style="emph">title</spanx> property of the event, or the overridden <spanx style="emph">title</spanx> property of a recurrence.</t>
<t><spanx style="strong">description</spanx>: <spanx style="verb">String|null</spanx>
Looks for the text in the <spanx style="emph">description</spanx> property of the event, or the overridden <spanx style="emph">description</spanx> property of a recurrence.</t>
<t><spanx style="strong">location</spanx>: <spanx style="verb">String|null</spanx>
Looks for the text in the <spanx style="emph">locations</spanx> property of the event (matching name/description of a location), or the overridden <spanx style="emph">locations</spanx> property of a recurrence.</t>
<t><spanx style="strong">owner</spanx>: <spanx style="verb">String|null</spanx>
Looks for the text in the name or email fields of a participant in the <spanx style="emph">participants</spanx> property of the event, or the overridden <spanx style="emph">participants</spanx> property of a recurrence, where the participant has a role of &quot;owner&quot;.</t>
<t><spanx style="strong">attendee</spanx>: <spanx style="verb">String|null</spanx>
Looks for the text in the name or email fields of a participant in the <spanx style="emph">participants</spanx> property of the event, or the overridden <spanx style="emph">participants</spanx> property of a recurrence, where the participant has a role of &quot;attendee&quot;.</t>
</list>
</t>
<t>If zero properties are specified on the FilterCondition, the condition MUST always evaluate to <spanx style="verb">true</spanx>. If multiple properties are specified, ALL must apply for the condition to be <spanx style="verb">true</spanx> (it is equivalent to splitting the object into one-property conditions and making them all the child of an AND filter operator).
</t>
<t>The exact semantics for matching <spanx style="verb">String</spanx> fields is <spanx style="strong">deliberately not defined</spanx> to allow for flexibility in indexing implementation, subject to the following:
</t>
<t>
<list style="symbols">
<t>Text SHOULD be matched in a case-insensitive manner.</t>
<t>Text contained in either (but matched) single or double quotes SHOULD be treated as a <spanx style="strong">phrase search</spanx>, that is a match is required for that exact sequence of words, excluding the surrounding quotation marks. Use <spanx style="verb">\"</spanx>, <spanx style="verb">\'</spanx> and <spanx style="verb">\\</spanx> to match a literal <spanx style="verb">"</spanx>, <spanx style="verb">'</spanx> and <spanx style="verb">\</spanx> respectively in a phrase.</t>
<t>Outside of a phrase, white-space SHOULD be treated as dividing separate tokens that may be searched for separately in the event, but MUST all be present for the event to match the filter.</t>
<t>Tokens MAY be matched on a whole-word basis using stemming (so for example a text search for <spanx style="verb">bus</spanx> would match &quot;buses&quot; but not &quot;business&quot;).</t>
</list>
</t>
</section>

<section anchor="sorting" title="Sorting">
<t>The following properties MUST be supported for sorting:
</t>
<t>
<list style="symbols">
<t>start</t>
<t>uid</t>
</list>
</t>
</section>
</section>

<section anchor="calendareventquerychanges" title="CalendarEvent/queryChanges">
<t>Standard &quot;/queryChanges&quot; method as described in <xref target="I-D.ietf-jmap-core"/> section 5.6.
</t>
</section>
</section>

<section anchor="security-considerations" title="Security considerations">
<t>All security considerations of JMAP (<xref target="I-D.ietf-jmap-core"/>) apply to this specification. Additional considerations specific to the data types and functionality introduced by this document are described in the following subsections.
</t>
<t>TODO
</t>
</section>

<section anchor="iana-considerations" title="IANA considerations">

<section anchor="jmap-capability-registration-for-calendars" title="JMAP capability registration for &quot;calendars&quot;">
<t>IANA will register the &quot;calendars&quot; JMAP Capability as follows:
</t>
<t>Capability Name: <spanx style="verb">urn:ietf:params:jmap:calendars</spanx>
</t>
<t>Specification document: this document
</t>
<t>Intended use: common
</t>
<t>Change Controller: IETF
</t>
<t>Security and privacy considerations: this document, section TODO
</t>
</section>
</section>

</middle>
<back>
<references title="Normative References">
<?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-calext-jscalendar.xml"?>
<?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-jmap-core.xml"?>
<?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"?>
<?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"?>
</references>

</back>
</rfc>
