draft-ietf-jmap-calendars-00.txt   draft-ietf-jmap-calendars-01.txt 
JMAP N. Jenkins JMAP N. Jenkins
Internet-Draft FastMail Internet-Draft Fastmail
Intended status: Standards Track M. Douglass Intended status: Standards Track M. Douglass
Expires: October 31, 2019 Spherical Cow Group Expires: April 30, 2020 Spherical Cow Group
April 29, 2019 October 28, 2019
JMAP for Calendars JMAP for Calendars
draft-ietf-jmap-calendars-00 draft-ietf-jmap-calendars-01
Abstract Abstract
This document specifies a data model for synchronising calendar data This document specifies a data model for synchronizing calendar data
with a server using JMAP. with a server using JMAP.
Status of This Memo Status of This Memo
This Internet-Draft is submitted in full conformance with the This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79. provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on October 31, 2019. This Internet-Draft will expire on April 30, 2020.
Copyright Notice Copyright Notice
Copyright (c) 2019 IETF Trust and the persons identified as the Copyright (c) 2019 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info) in effect on the date of (https://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License. described in the Simplified BSD License.
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. Notational conventions . . . . . . . . . . . . . . . . . 2 1.1. Data Model Overview . . . . . . . . . . . . . . . . . . . 3
1.2. The Date datatypes . . . . . . . . . . . . . . . . . . . 3 1.2. Accounts, Push, and the Session Object . . . . . . . . . 4
1.3. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 1.2.1. UIDs and CalendarEvent Ids . . . . . . . . . . . . . 5
1.4. Addition to the capabilities object . . . . . . . . . . . 3 1.3. Notational Conventions . . . . . . . . . . . . . . . . . 5
2. Calendars . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.4. The LocalDate Data Type . . . . . . . . . . . . . . . . . 6
2.1. Calendar/get . . . . . . . . . . . . . . . . . . . . . . 5 1.5. Terminology . . . . . . . . . . . . . . . . . . . . . . . 6
2.2. Calendar/changes . . . . . . . . . . . . . . . . . . . . 5 1.6. Addition to the Capabilities Object . . . . . . . . . . . 6
2.3. Calendar/set . . . . . . . . . . . . . . . . . . . . . . 5 1.6.1. urn:ietf:params:jmap:calendars . . . . . . . . . . . 6
3. Calendar events . . . . . . . . . . . . . . . . . . . . . . . 5 1.6.2. urn:ietf:params:jmap:calendarprincipals . . . . . . . 7
3.1. CalendarEvent/get . . . . . . . . . . . . . . . . . . . . 6 2. Calendar Principals . . . . . . . . . . . . . . . . . . . . . 8
3.2. CalendarEvent/changes . . . . . . . . . . . . . . . . . . 6 2.1. CalendarPrincipal/get . . . . . . . . . . . . . . . . . . 9
3.3. CalendarEvent/set . . . . . . . . . . . . . . . . . . . . 6 2.2. CalendarPrincipal/changes . . . . . . . . . . . . . . . . 9
3.4. CalendarEvent/copy . . . . . . . . . . . . . . . . . . . 6 2.3. CalendarPrincipal/set . . . . . . . . . . . . . . . . . . 9
3.5. CalendarEvent/query . . . . . . . . . . . . . . . . . . . 7 2.4. CalendarPrincipal/query . . . . . . . . . . . . . . . . . 9
3.5.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 7 2.4.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 9
3.5.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 8 2.5. CalendarPrincipal/queryChanges . . . . . . . . . . . . . 10
3.6. CalendarEvent/queryChanges . . . . . . . . . . . . . . . 8 2.6. CalendarPrincipal/getAvailability . . . . . . . . . . . . 10
4. Security considerations . . . . . . . . . . . . . . . . . . . 8 3. Calendars . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5. IANA considerations . . . . . . . . . . . . . . . . . . . . . 9 3.1. Calendar/get . . . . . . . . . . . . . . . . . . . . . . 17
5.1. JMAP capability registration for "calendars" . . . . . . 9 3.2. Calendar/changes . . . . . . . . . . . . . . . . . . . . 17
6. Normative References . . . . . . . . . . . . . . . . . . . . 9 3.3. Calendar/set . . . . . . . . . . . . . . . . . . . . . . 17
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 9 4. Calendar Share Notifications . . . . . . . . . . . . . . . . 18
4.1. Auto-deletion of Notifications . . . . . . . . . . . . . 19
4.2. Object Properties . . . . . . . . . . . . . . . . . . . . 19
4.3. CalendarShareNotification/get . . . . . . . . . . . . . . 20
4.4. CalendarShareNotification/changes . . . . . . . . . . . . 20
4.5. CalendarShareNotification/set . . . . . . . . . . . . . . 20
4.6. CalendarShareNotification/query . . . . . . . . . . . . . 20
4.6.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 20
4.6.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 20
4.7. CalendarShareNotification/queryChanges . . . . . . . . . 20
5. Calendar Events . . . . . . . . . . . . . . . . . . . . . . . 20
5.1. Attachments . . . . . . . . . . . . . . . . . . . . . . . 21
5.2. Per-user properties . . . . . . . . . . . . . . . . . . . 22
5.3. Recurring events . . . . . . . . . . . . . . . . . . . . 22
5.4. CalendarEvent/get . . . . . . . . . . . . . . . . . . . . 23
5.5. CalendarEvent/changes . . . . . . . . . . . . . . . . . . 24
5.6. CalendarEvent/set . . . . . . . . . . . . . . . . . . . . 24
5.6.1. Sending invitations and responses . . . . . . . . . . 25
5.7. CalendarEvent/copy . . . . . . . . . . . . . . . . . . . 28
5.8. CalendarEvent/query . . . . . . . . . . . . . . . . . . . 28
5.8.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 29
5.8.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 30
5.9. CalendarEvent/queryChanges . . . . . . . . . . . . . . . 31
5.10. Examples . . . . . . . . . . . . . . . . . . . . . . . . 31
6. Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
6.1. Push events . . . . . . . . . . . . . . . . . . . . . . . 31
6.2. Acknowledging an alert . . . . . . . . . . . . . . . . . 32
6.3. Snoozing an alert . . . . . . . . . . . . . . . . . . . . 32
7. Calendar Event Notifications . . . . . . . . . . . . . . . . 33
7.1. Auto-deletion of Notifications . . . . . . . . . . . . . 33
7.2. Object Properties . . . . . . . . . . . . . . . . . . . . 33
7.3. CalendarEventNotification/get . . . . . . . . . . . . . . 34
7.4. CalendarEventNotification/changes . . . . . . . . . . . . 34
7.5. CalendarEventNotification/set . . . . . . . . . . . . . . 34
7.6. CalendarEventNotification/query . . . . . . . . . . . . . 35
7.6.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 35
7.6.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 35
7.7. CalendarEventNotification/queryChanges . . . . . . . . . 35
8. Security Considerations . . . . . . . . . . . . . . . . . . . 35
8.1. Denial-of-service Expanding Recurrences . . . . . . . . . 35
8.2. Privacy . . . . . . . . . . . . . . . . . . . . . . . . . 36
9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 36
9.1. JMAP Capability Registration for "calendars" . . . . . . 36
9.2. Reservation of JMAP attributes in JSCalendar Property
registry . . . . . . . . . . . . . . . . . . . . . . . . 36
10. References . . . . . . . . . . . . . . . . . . . . . . . . . 36
10.1. Normative References . . . . . . . . . . . . . . . . . . 36
10.2. Informative References . . . . . . . . . . . . . . . . . 37
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 37
1. Introduction 1. Introduction
JMAP ([I-D.ietf-jmap-core] - JSON Meta Application Protocol) is a JMAP ([RFC8620] - JSON Meta Application Protocol) is a generic
generic protocol for synchronising data, such as mail, calendars or protocol for synchronizing data, such as mail, calendars or contacts,
contacts, between a client and a server. It is optimised for mobile between a client and a server. It is optimized for mobile and web
and web environments, and aims to provide a consistent interface to environments, and aims to provide a consistent interface to different
different data types. data types.
This specification defines a data model for synchronising calendar This specification defines a data model for synchronizing calendar
data between a client and a server using JMAP. data between a client and a server using JMAP. The data model is
designed to allow a server to provide consistent access to the same
data via CalDAV [RFC4791] as well as JMAP, however the functionality
offered over the two protocols may differ. Unlike CalDAV, this
specification does not define access to tasks or journal entries
(VTODO or VJOURNAL iCalendar components in CalDAV).
1.1. Notational conventions 1.1. Data Model Overview
A CalendarPrincipal (see Section XXX) represents an individual, team
or resource (e.g. a room or projector). The object contains
information about the entity being represented, such as a name,
description and time zone. A CalendarPrincipal has a 1:1
correspondence with an Account (see [RFC8620], Section 1.6.2) that
supports the "urn:ietf:params:jmap:calendars" capability.
Each such Account contains zero or more Calendar objects, which is a
named collection of CalendarEvents belonging to the
CalendarPrincipal. Sharing permissions are managed per calendar.
For example, an individual may have separate calendars for personal
and work activities, with both contributing to their free-busy
availability, but only the work calendar shared in its entirety with
colleagues. Calendars can also provide defaults, such as alerts and
a color to apply to events in the calendar. Clients commonly let
users toggle visibility of events belonging to a particular calendar
on/off.
A CalendarEvent is a representation of an event or recurring series
of events in JSEvent [I-D.ietf-calext-jscalendar] format. Simple
clients may ask the server to expand recurrences for them within a
specific time period, and optionally convert times into UTC so they
do not have to handle time zone conversion. More full-featured
clients will want to access the full event information and handle
recurrence expansion and time zone conversion locally.
CalendarEventNotification objects keep track of the history of
changes made to a calendar by other users, allowing calendar clients
to notify the user of changes to their schedule. Similarly, the
CalendarShareNotification type notifies the user when their access to
another user's calendar is granted or revoked.
1.2. Accounts, Push, and the Session Object
The JMAP Session object (see [RFC8620], Section 2) typically includes
an object in the "accounts" property for every account that the user
has access to. Calendaring systems may share data between a
(potentially very) large number of CalendarPrincipals, most of which
the user does not care about day-to-day but may occasionally need to
query when scheduling events.
Users can normally subscribe to any calendar to which they have
access (see Section XXX). This indicates the user wants this
calendar to appear in their regular list of calendars. The separate
"isVisible" property stores whether the user would currently like to
view the events in a subscribed calendar.
The Session object MUST only include Accounts where the user is
subscribed to at least one Calendar or they have access to some other
data type in the account. StateChange events for changes to
CalendarEvent data SHOULD only be sent for events in calendars the
user has subscribed to and MUST NOT be sent for any Account where the
user is not subscribed to at least one calendar.
The server MAY reject the user's attempt to subscribe to some
calendars, e.g. those representing resources.
A user may query the set of CalendarPrincipals they have access to
with "CalendarPrincipal/query" (see Section XXX). The
CalendarPrincipal object may have an "accountId" property that can be
used to then fetch calendars and events associated with that
principal, subject to appropriate permissions.
1.2.1. UIDs and CalendarEvent Ids
Each CalendarEvent has a "uid" property
([I-D.ietf-calext-jscalendar], Section 4.1.2), which is a globally
unique identifier that identifies the same event in different
Accounts, or different instances of the same recurring event within
an Account.
An Account MUST NOT contain more than one CalendarEvent with the same
uid unless all of the CalendarEvent objects have distinct, non-null
values for their "recurrenceId" property. (This situation occurs if
the principal is added to one or more specific instances of a
recurring event without being invited to the whole series.)
Each CalendarEvent also has an id, which is scoped to the JMAP
Account and used for referencing it in JMAP methods. There is no
necessary link between the uid property and the CalendarEvent's id.
CalendarEvents with the same uid in different Accounts MAY have
different ids.
1.3. Notational Conventions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP "OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119] [RFC8174] when, and only when, they appear in all 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here. capitals, as shown here.
Type signatures, examples and property descriptions in this document Type signatures, examples, and property descriptions in this document
follow the conventions established in section 1.1 of follow the conventions established in Section 1.1 of [RFC8620]. Data
[I-D.ietf-jmap-core]. types defined in the core specification are also used in this
document.
Object properties may also have a set of attributes defined along 1.4. The LocalDate Data Type
with the type signature. These have the following meanings:
o *server-set*: Only the server can set the value for this property. Where "LocalDate" is given as a type, it means a string in the same
The client MUST NOT send this property when creating a new object format as "Date" (see [RFC8620], Section 1.4), but with the "time-
of this type. offset" 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,
"2014-10-30T14:12:00".
o *immutable*: The value MUST NOT change after the object is 1.5. Terminology
created.
o *default*: (This is followed by a JSON value). The value that The same terminology is used in this document as in the core JMAP
will be used for this property if it is omitted in an argument, or specification, see [RFC8620], Section 1.6.
when creating a new object of this type.
Data types defined in the core specification are used in this The terms CalendarPrincipal, Calendar, CalendarEvent,
document. CalendarEventNotification, and CalendarShareNotification (with these
specific capitalizations) are used to refer to the data types defined
in this document and instances of those data types.
1.2. The Date datatypes 1.6. Addition to the Capabilities Object
Where "LocalDate" is given as a type, it means a string in the same The capabilities object is returned as part of the JMAP Session
format as "Date", but with the _time-offset_ omitted from the end. object; see [RFC8620], Section 2. This document defines two
The interpretation in absolute time depends upon the time zone for additional capability URIs.
the event, which may not be a fixed offset (for example when daylight
saving time occurs). For example, ""2014-10-30T14:12:00"".
1.3. Terminology 1.6.1. urn:ietf:params:jmap:calendars
The same terminology is used in this document as in the core JMAP This represents support for the Calendar, CalendarEvent, and
specification. CalendarEventNotification data types and associated API methods. The
value of this property in the JMAP Session capabilities property is
an empty object.
1.4. Addition to the capabilities object The value of this property in an account's accountCapabilities
property is an object that MUST contain the following information on
server capabilities and permissions for that account:
The capabilities object is returned as part of the standard JMAP o *accountIdForCalendarPrincipal*: "String|null" The id of an
Session object; see the JMAP spec. Servers supporting _this_ account with the "urn:ietf:params:jmap:calendarprincipals"
specification MUST add a property called capability that contains the corresponding CalendarPrincipal
"urn:ietf:params:jmap:calendars" to the capabilities object. object. This may be the same account id. This is null for
single-user systems that do not support the CalendarPrincipal data
type.
The value of this property is an empty object in both the JMAP o *maxSizeCalendarEvent*: "UnsignedInt" The maximum size in octets
session _capabilities_ property and an account's of the largest CalendarEvent the server is willing to store.
_accountCapabilities_ property. TODO: How can you relate this to what the client knows?
2. Calendars o *minDateTime*: "LocalDate" The earliest date-time the server is
willing to accept for any date stored in a CalendarEvent.
o *maxDateTime*: "LocalDate" The latest date-time the server is
willing to accept for any date stored in a CalendarEvent.
o *maxExpandedQueryDuration*: "Duration" The maximum duration the
user may query over when asking the server to expand recurrences.
o *maxParticipantsPerEvent*: "Number|null" The maximum number of
participants a single event may have, or null for no limit.
o *maxNumberEventNotifications*: "UnsignedInt" The maximum number of
CalendarEventNotification objects the server will store for this
account. If new notifications are added in excess of this number,
older notifications will be automatically deleted by the server.
o *mayCreateCalendar*: "Boolean" If true, the user may create a
calendar in this account.
1.6.2. urn:ietf:params:jmap:calendarprincipals
Represents support for the CalendarPrincipal and
CalendarShareNotification data types and associated API methods.
Single user systems do not need this and MAY choose not to support
it.
The value of this property in the JMAP Session capabilities property
is an empty object.
The value of this property in an account's accountCapabilities
property is an object that MUST contain the following information on
server capabilities and permissions for that account:
o *currentUserPrincipalId*: "String|null" The id of the principal in
this account that corresponds to the user fetching this object, if
any.
o *maxAvailabilityDuration*: The maximum duration over which the
server is prepared to calculate availability in a single call (see
Section XXX).
o *maxNumberShareNotifications*: "UnsignedInt" The maximum number of
CalendarShareNotification objects the server will store for a
principal in this account. If new notifications are added in
excess of this number, older notifications will be automatically
deleted by the server.
2. Calendar Principals
A CalendarPrincipal represents an individual, group, schedulable
location (e.g. a room), bookable resource (e.g. a projector) or other
entity in the calendar system. In a shared calendar environment such
as a workplace, a user may have access to a large number of
principals.
In most systems the user will have access to a single Account
containing CalendarPrincipal objects, but they may have access to
multiple if, for example, aggregating calendar data from different
places.
A *CalendarPrincipal* object has the following properties:
o *id*: "Id" The id of the principal.
o *name*: "String" The name of the principal, e.g. "Jane Doe", or
"Room 4B".
o *description*: "String|null" A longer description of the
principal, for example details about the facilities of a resource,
or null if no description available.
o *email*: "String|null" An email address for the principal, or null
if no email is available.
o *type*: "String" This MUST be one of the following values:
* "individual": This represents a single person.
* "group": This represents a group of people.
* "resource": This represents some resource, e.g. a projector.
* "location": This represents a location.
* "other": This represents some other undefined principal.
o *timeZone*: "String" The time zone for this principal. The value
MUST be a time zone id from the IANA Time Zone Database.
o *mayGetAvailability*: "Boolean" May the user call the
"CalendarPrincipal/getAvailability" method with this
CalendarPrincipal?
o *accountId*: "Id|null" Id of Account with the
"urn:ietf:params:jmap:calendars" capability that contains the data
for this principal, or null if none (e.g. the CalendarPrincipal is
a group just used for permissions management), or the user does
not have access to any data in the account (with the exception of
free/busy, which is governed by the mayGetAvailability property).
o *account*: "Account|null" The JMAP Account object corresponding to
the accountId, null if none.
o *sendTo*: "String[String]|null" If this principal may be added as
a participant to an event, this is the map of methods for adding
it, in the same format as Participant#sendTo in JSEvent (see
[I-D.ietf-calext-jscalendar], Section 4.4.5).
2.1. CalendarPrincipal/get
This is a standard "/get" method as described in [RFC8620],
Section 5.1.
2.2. CalendarPrincipal/changes
This is a standard "/changes" method as described in [RFC8620],
Section 5.2.
2.3. CalendarPrincipal/set
This is a standard "/set" method as described in [RFC8620],
Section 5.3. However, the user may only update the "timeZone"
property of the CalendarPrincipal with the same id as the
"currentUserPrincipalId" in the Account capabilities. Any other
change MUST be rejected with a "forbidden" SetError.
Managing calendar principals is likely tied to a directory service or
some other vendor-specific solution, and occurs out-of-band, or via
an additional capability defined elsewhere.
2.4. CalendarPrincipal/query
This is a standard "/query" method as described in [RFC8620],
Section 5.5
2.4.1. Filtering
A *FilterCondition* object has the following properties:
o *accountIds*: "String[]" A list of account ids. The
CalendarPrincipal matches if the value for its accountId property
is in this list.
o *email*: "String" Looks for the text in the email property.
o *name*: "String" Looks for the text in the name property.
o *text* "String" Looks for the text in the name, email, and
description properties.
o *type*: "String" The type must be exactly as given to match the
condition.
o *timeZone*: "String" The timeZone must be exactly as given to
match the condition.
All conditions in the FilterCondition object must match for the
CalendarPrincipal to match.
2.5. CalendarPrincipal/queryChanges
This is a standard "/queryChanges" method as described in [RFC8620],
Section 5.6.
2.6. CalendarPrincipal/getAvailability
Calculates the availability of the principal for scheduling within a
requested time period. It takes the following arguments:
o *accountId*: "Id" The id of the account to use.
o *id*: "Id" The id of the CalendarPrincipal to calculate
availability for.
o *utcStart*: "UTCDate" The start time (inclusive) of the period for
which to return availability.
o *utcEnd*: "UTCDate" The end time (exclusive) of the period for
which to return availability.
o *showDetails*: "Boolean" If true, event details will be returned
if the user has permission to view them.
The server will first find all relevant events, expanding any
recurring events. Relevant events are ones where all of the
following is true:
o The principal is subscribed to the calendar.
o Either the calendar belongs to the principal or the "shareesActAs"
property of the calendar is "self".
o The "includeInAvailability" property of the calendar for the
principal is "all" or "attending".
o The user has the "mayReadFreeBusy" permission for the calendar.
o The event finishes after the "utcStart" argument and starts before
the "utcEnd" argument.
o The event's "privacy" property is not "secret".
o The "freeBusyStatus" property of the event is "busy" (or omitted,
as this is the default).
o The "status" property of the event is not "cancelled".
o If the "includeInAvailability" property of the calendar is
"attending", then the principal is a participant of the event, and
has a "participationStatus" of "accepted" or "tentative".
The server then generates a BusyPeriod object for each of these
events. A *BusyPeriod* object has the following properties:
o *utcStart*: "UTCDate" The start time (inclusive) of the period
this represents.
o *utcEnd*: "UTCDate" The end time (exclusive) of the period this
represents.
o *busyStatus*: "String" (optional, default "unavailable") This MUST
be one of
* "confirmed": The event status is "confirmed".
* "tentative": The event status is "tentative".
* "unavailable": The principal is not available for scheduling at
this time for any other reason.
o *event*: "JSEvent|null" The JSEvent representation of the event,
or null if any of the following are true:
* The "showDetails" argument is false.
* The "privacy" property of the event is "private".
* The user does not have the "mayReadItems" permission for the
calendar.
The server MAY also generate BusyPeriod objects based on other
information it has about the principal's availability, such as office
hours.
Finally, the server MUST merge and split BusyPeriod objects where the
"event" property is null, such that none of them overlap and either
there is a gap in time between any two objects (the utcEnd of one
does not equal the utcStart of another) or those objects have a
different busyStatus property. If there are overlapping BusyPeriod
time ranges with different "busyStatus" properties the server MUST
choose the value in the following order: confirmed > unavailable >
tentative.
The response has the following arguments:
o *accountId*: "Id" The id of the account used for the call.
o *id*: "Id" The id of the CalendarPrincipal availability is being
returned for.
o *utcStart*: "UTCDate" The start time (inclusive) of the period for
which availability is being returned.
o *utcEnd*: "UTCDate" The end time (exclusive) of the period for
which availability is being returned.
o *list*: "BusyPeriod[]" The list of BusyPeriod objects calculated
as described above.
The following additional errors may be returned instead of the
"CalendarPrincipal/getAvailability" response:
"notFound": No principal with this id exists, or the user does not
have permission to see that this principal exists.
"forbidden": The user does not have permission to query this
principal's availability.
"tooLarge": The duration between utcStart an utcEnd is longer than
the server is willing to calculate availability for.
"rateLimit": Too many availability requests have been made recently
and the user is being rate limited. It may work to try again later.
3. Calendars
A Calendar is a named collection of events. All events are A Calendar is a named collection of events. All events are
associated with one, and only one, calendar. associated with one, and only one, calendar.
A *Calendar* object has the following properties: A *Calendar* object has the following properties:
o *id*: "Id" (immutable; server-set) The id of the calendar. o *id*: "Id" (immutable; server-set) The id of the calendar.
o *role*: "String|null" Denotes the calendar has a special purpose.
This MUST be one of the following:
* "inbox": This is the principal's default calendar; when the
principal is invited to an event, this is the calendar to which
it will be added by the server. There MUST NOT be more than
one calendar with this role in an account.
* "templates": This calendar holds templates for creating new
events. All events in this calendar MUST have the "isDraft"
property set to true. Clients should not show this as a
regular calendar to users, but may offer users to create new
events by copying one of the events in here.
o *name*: "String" The user-visible name of the calendar. This may o *name*: "String" The user-visible name of the calendar. This may
be any UTF-8 string of at least 1 character in length and maximum be any UTF-8 string of at least 1 character in length and maximum
255 octets in size. 255 octets in size.
o *color*: "String" Any valid CSS color value. The color to be used o *description*: "String|null" An optional longer-form description
when displaying events associated with the calendar. The color of the calendar, to provide context in shared environments where
SHOULD have sufficient contrast to be used as text on a white users need more than just the name.
background.
o *color*: "String" The color to be used when displaying events
associated with the calendar. The value MUST be a case-
insensitive color name taken from the CSS3 set of names, defined
in Section 4.3 of W3C.REC-css3-color-20110607, or a CSS3 RGB color
hex value. The color SHOULD have sufficient contrast to be used
as text on a white background.
o *sortOrder*: "UnsignedInt" (default: 0) Defines the sort order of o *sortOrder*: "UnsignedInt" (default: 0) Defines the sort order of
calendars when presented in the client's UI, so it is consistent calendars when presented in the client's UI, so it is consistent
between devices. The number MUST be an integer in the range 0 <= between devices. The number MUST be an integer in the range 0 <=
sortOrder < 2^31. A calendar with a lower order should be sortOrder < 2^31. A calendar with a lower order should be
displayed before a calendar with a higher order in any list of displayed before a calendar with a higher order in any list of
calendars in the client's UI. Calendars with equal order should calendars in the client's UI. Calendars with equal order SHOULD
be sorted in alphabetical order by name. The sorting should take be sorted in alphabetical order by name. The sorting should take
into locale-specific character order convention. into account locale-specific character order convention.
o *isSubscribed*: "Boolean" Has the user indicated they wish to see
this Calendar in their client? This SHOULD default to false for
Calendars in shared accounts the user has access to and true for
any new Calendars created by the user themself. If false, the
calendar should only be displayed when the user explicitly
requests it or to offer it for the user to subscribe to.
o *isVisible*: "Boolean" (default: true) Should the calendar's o *isVisible*: "Boolean" (default: true) Should the calendar's
events be displayed to the user at the moment? events be displayed to the user at the moment? Clients MUST
ignore this property if isSubscribed is false.
o *mayReadFreeBusy*: "Boolean" (server-set) The user may read the o *includeInAvailability*: "String" (default: all) Should the
free-busy information for this calendar. In JMAP terms, this calendar's events be used as part of availability calculation?
means the user may use this calendar as part of a filter in a This MUST be one of:
_CalendarEvent/query_ call, however unless "mayRead == true", the
events returned for this calendar will only contain free-busy
information, and be stripped of any other data. This property
MUST be "true" if _mayRead_ is "true".
o *mayReadItems*: "Boolean" (server-set) The user may fetch the * "all": all events are considered.
events in this calendar. In JMAP terms, this means the user may
use this calendar as part of a filter in a _CalendarEvent/query_
call
o *mayAddItems*: "Boolean" (server-set) The user may add events to * "attending": events the user is a confirmed or tentative
this calendar. In JMAP terms, this means the user may call participant of are considered.
_CalendarEvent/set_ to create new events in this calendar or move
existing events into this calendar from another calendar. This
property MUST be "false" if the account to which this calendar
belongs has the _isReadOnly_ property set to "true".
o *mayModifyItems*: "Boolean" (server-set) The user may edit events * "none": all events are ignored.
in this calendar by calling _CalendarEvent/set_ with the _update_
argument referencing events in this collection. This property
MUST be "false" if the account to which this calendar belongs has
the _isReadOnly_ property set to "true".
o *mayRemoveItems*: "Boolean" (server-set) The user may remove o *defaultAlertsWithTime*: "Alert[]" The alerts to apply for events
events from this calendar by calling _CalendarEvent/set_ with the where showWithoutTime is false that have "useDefaultAlerts" set.
_destroy_ argument referencing events in this collection, or by See [I-D.ietf-calext-jscalendar], Section 4.5.2 for the definition
updating their _calendarId_ property to a different calendar. of an Alert object.
This property MUST be "false" if the account to which this
calendar belongs has the _isReadOnly_ property set to "true".
o *mayRename*: "Boolean" (server-set) The user may rename the o *defaultAlertsWithoutTime*: "Alert[]" The alerts to apply for
calendar. This property MUST be "false" if the account to which events where showWithoutTime is true that have "useDefaultAlerts"
this calendar belongs has the _isReadOnly_ property set to "true". set. See [I-D.ietf-calext-jscalendar], Section 4.5.2 for the
definition of an Alert object.
o *timeZone*: "String|null" The time zone to use for events without
a time zone when the server needs to resolve them into absolute
time, e.g., for reminders, queries, or availability calculation.
The value MUST be a time zone id from the IANA Time Zone Database.
If "null", the timeZone of the account's associated
CalendarPrincipal will be used. Clients SHOULD use this as the
default for new events in this calendar if set.
o *participantIdentities*: "ParticipantIdentity[]|null" (server-set)
The identities that represent the user in this calendar. The
first item in the array is the default. A *ParticipantIdentity*
object has the following properties:
* *name*: "String" The display name of the participant to use
when adding this participant to an event, e.g. "Joe Bloggs".
* *type*: "String" The method for sending scheduling messages to
this identity, e.g. "imip"
* *uri*: "String" The URI for sending scheduling messages to this
identity, e.g. "mailto:foo@example.com"
The user is an *owner* for an event if the CalendarEvent object
has a "participants" property, and one of the Participant objects
has both: a) The "owner" role. b) A "sendTo" property that has
"type" and "uri" equal to one of the ParticipantIdentity objects
returned with the calendar.
o *shareWith*: "Id[CalendarRights]|null" A map of CalendarPrincipal
id to rights for principals this calendar is shared with. The
pricincipal to which this calendar belongs MUST NOT be in this
set. This is null if the user requesting the object does not have
the mayAdmin right, or if the calendar is not shared with anyone.
May be modified only if the user has the mayAdmin right.
o *shareesActAs*: "String" (immutable; default server-dependent)
This MUST be one of:
* "owner"
* "self"
If "self", sharees act as themselves when using this calendar. If
"owner", they act as the pricincipal to which this calendar
belongs (secretary mode). If omitted, the default is server
dependent. For example, it may be "self" if creating a calendar
in a CalendarPrincipal representing a group, and "owner" if
creating a calendar for an individual. Users may attempt to set
this on creation, but the server may reject with an
"invalidProperties" error if the value is not permissible.
o *myRights*: "CalendarRights" (server-set) The set of access rights
the user has in relation to this Calendar.
A *CalendarRights* object has the following properties:
o *mayReadFreeBusy*: "Boolean" The user may read the free-busy
information for this calendar as part of a call to
CalendarPrincipal/getAvailability (see Section XXX).
o *mayReadItems*: "Boolean" The user may fetch the events in this
calendar.
o *mayAddItems*: "Boolean" The user may create new events on this
calendar or move events to this calendar. For recurring events,
they may add an override to add an occurrence, or remove an
existing override that is excluding an occurrence.
o *mayUpdatePrivate*: "Boolean" The user may modify the following
properties on all events in the calendar. If shareesActAs is
"self", these properties MUST all be stored per-user, and changes
do not affect any other user of the calendar. If shareesActAs is
"owner", the values are shared between all users.
* keywords
* color
* freeBusyStatus
* useDefaultAlerts
* alerts
The user may also modify the above on a per-occurrence basis for
recurring events.
o *mayRSVP*: "Boolean" The user may modify the
"participationStatus", "participationComment", "expectReply" and
"scheduleAgent" properties of any Participant object that is
represented in the "participantIdentities" property of the
calendar. The user may also modify the above on a per-occurrence
basis for recurring events.
o *mayUpdateOwn*: "Boolean" The user may modify an existing event on
this calendar if either they are the owner of the event or the
event has no owner.
o *mayUpdateAll*: "Boolean" The user may modify all existing events
on this calendar.
o *mayRemoveOwn*: "Boolean" The user may delete an event or move it
to a different calendar if either they are the owner of the event
or the event has no owner. For recurring events, they may add an
override to remove an occurrence.
o *mayRemoveAll*: "Boolean" The user may delete any event or move it
to a different calendar. For recurring events, they may add an
override to remove an occurrence.
o *mayAdmin*: "Boolean" The user may modify sharing for this
calendar.
o *mayDelete*: "Boolean" (server-set) The user may delete the o *mayDelete*: "Boolean" (server-set) The user may delete the
calendar itself. This property MUST be "false" if the account to calendar itself. This property MUST be false if the account to
which this calendar belongs has the _isReadOnly_ property set to which this calendar belongs has the _isReadOnly_ property set to
"true". true.
2.1. Calendar/get 3.1. Calendar/get
Standard "/get" method as described in [I-D.ietf-jmap-core] section This is a standard "/get" method as described in [RFC8620],
5.1. The _ids_ argument may be "null" to fetch all at once. Section 5.1. The _ids_ argument may be "null" to fetch all at once.
2.2. Calendar/changes If mayReadFreeBusy is the only permission the user has, the calendar
MUST NOT be returned in Calendar/get and Calendar/query; it must
behave as though it did not exist. The data is just used as part of
CalendarPrincipal/getAvailability.
Standard "/changes" method as described in [I-D.ietf-jmap-core] 3.2. Calendar/changes
section 5.2.
2.3. Calendar/set This is a standard "/changes" method as described in [RFC8620],
Section 5.2.
Standard "/set" method as described in [I-D.ietf-jmap-core] section 3.3. Calendar/set
5.3.
A calendar MAY be deleted that is currently associated with one or This is a standard "/set" method as described in [RFC8620],
more events. In this case, the events belonging to this calendar Section 5.3 but with the following additional request argument:
MUST also be deleted. Conceptually, this MUST happen prior to the
calendar itself being deleted, and MUST generate a *push* event that
modifies the state of the _CalendarEvent_ type for the account.
3. Calendar events o *onDestroyRemoveEvents*: "Boolean" (default: false)
If false, any attempt to destroy a Calendar that still has
CalendarEvents in it will be rejected with a "calendarHasEvents"
SetError. If true, any CalendarEvents that were in the Calendar will
be destroyed. This SHOULD NOT send scheduling messages to
participants or create CalendarEventNotification objects.
The role and shareWith properties may only be set by users that have
the mayAdmin right. The value is shared across all users, although
users without the mayAdmin right cannot see the value.
Users can subscribe or unsubscribe to a calendar by setting the
isSubscribed property. The server MAY forbid users from subscribing
to certain calendars even though they haver permission to see them,
rejecting the update with a "forbidden" SetError.
The timeZone, includeInAvailability, defaultAlertsWithoutTime and
defaultAlertsWithTime properties are stored per-user if the calendar
shareesActAs is "self" and may be set by any user who is subscribed
to the calendar. Otherwise, these properties are shared, and may
only be set by users that have the mayAdmin right.
The following properties may be set by anyone who is subscribed to
the calendar and are all stored per-user:
o name
o description
o color
o sortOrder
o isVisible
These properties are initially inherited from the owner's copy of the
calendar, but if set by a sharee that user gets their own copy of the
property; it does not change for any other principals. If the value
of the property in the owner's calendar changes after this, it does
not overwrite the sharee's value.
The following extra SetError types are defined:
For "destroy":
o *calendarHasEvent*: The Calendar has at least one CalendarEvent
assigned to it, and the "onDestroyRemoveEvents" argument was
false.
4. Calendar Share Notifications
The CalendarShareNotification data type records when the user's
permissions to access a shared calendar changes.
CalendarShareNotification are only created by the server; users
cannot create them explicitly. Notifications are stored in the same
Account as the CalendarPrincipals.
Clients SHOULD present the list of notifications to the user and
allow them to dismiss them. To dismiss a notification you use a
standard "/set" call to destroy it.
The server SHOULD create a CalendarShareNotification whenever the
user's permissions change on a calendar. It SHOULD NOT create a
notification for permission changes to a group principal, even if the
user is in the group.
4.1. Auto-deletion of Notifications
The server MAY limit the maximum number of notifications it will
store for a user. When the limit is reached, any new notification
will cause the previously oldest notification to be automatically
deleted.
The server MAY coalesce events if appropriate, or remove events that
it deems are no longer relevant or after a certain period of time.
The server SHOULD automatically destroy a notification about a
calendar if the user subscribes to that calendar.
4.2. Object Properties
The *CalendarShareNotification* object has the following properties:
o *id*: "String" The id of the CalendarShareNotification.
o *created*: "UTCDate" The time this notification was created.
o *changedBy*: "Person" Who made the change.
* *name*: "String" The name of the person who made the change.
* *email*: "String" The email of the person who made the change.
* *calendarPrincipalId*: "String|null" The id of the calendar
principal corresponding to the person who made the change.
o *calendarAccountId*: "String" The id of the account where this
calendar exists.
o *calendarId*: "String" The id of the CalendarEvent that this
notification is about.
o *calendarName*: "String" The name of the calendar at the time the
notification was made.
o *oldRights*: "CalendarRights|null" The rights the user had before
the change.
o *newRights*: "CalendarRights|null" The rights the user has after
the change.
4.3. CalendarShareNotification/get
This is a standard "/get" method as described in [RFC8620],
Section 5.1.
4.4. CalendarShareNotification/changes
This is a standard "/changes" method as described in [RFC8620],
Section 5.2.
4.5. CalendarShareNotification/set
This is a standard "/changes" method as described in [RFC8620],
Section 5.3.
Only destroy is supported; any attempt to create/update MUST be
rejected with a "forbidden" SetError.
4.6. CalendarShareNotification/query
This is a standard "/query" method as described in [RFC8620],
Section 5.5.
4.6.1. Filtering
A *FilterCondition* object has the following properties:
o *after*: "UTCDate|null" The creation date must be on or after this
date to match the condition.
o *before*: "UTCDate|null" The creation date must be before this
date to match the condition.
4.6.2. Sorting
The "created" property MUST be supported for sorting.
4.7. CalendarShareNotification/queryChanges
This is a standard "/queryChanges" method as described in [RFC8620],
Section 5.6.
5. Calendar Events
A *CalendarEvent* object contains information about an event, or A *CalendarEvent* object contains information about an event, or
recurring series of events, that takes place at a particular time. recurring series of events, that takes place at a particular time.
It is a JSEvent object, as defined in [I-D.ietf-calext-jscalendar], It is a JSEvent object, as defined in [I-D.ietf-calext-jscalendar],
with the following additional properties: with the following additional properties:
o *id*: "Id" The id of the event. This property is immutable. o *id*: "Id" The id of the CalendarEvent. This property is
immutable. The id uniquely identifies a JSEvent with a particular
"uid" and "recurrenceId" within a particular account.
o *calendarId*: "Id" The id of the calendar this event belongs to. o *calendarId*: "Id" The id of the Calendar this event belongs to.
o *participantId*: "Id|null" The id of the participant in the o *isDraft*: "Boolean" If true, this event is to be considered a
_participants_ object which corresponds to the account this event draft; the server will not send any scheduling messages to
is in. participants while this is true. To use, this must be set on
creation. Once set to false, the value cannot be updated to true.
3.1. CalendarEvent/get o *utcStart*: "UTCDate" For simple clients that do not or cannot
implement time zone support. Clients should only use this if also
asking the server to expand recurrences, as you cannot accurately
expand a recurrence without the original time zone. This property
is calculated at fetch time by the server. Time zones are
political and they can and do change at any time. Fetching
exactly the same property again may return a different results if
the time zone data has been updated on the server. Time zone data
changes are not considered "updates" to the event. If set, server
will convert to the event's current time zone using its current
time zone data and store the local time. This is not included by
default and must be requested explicitly. Floating events will be
interpreted as per calendar's time zone property; or if not set,
the the principal's time zone property.
Standard "/get" method as described in [I-D.ietf-jmap-core] section o *utcEnd*: "UTCDate" The server calculates the end time in UTC from
5.1. the start/timeZone/duration properties of the event. This is not
included by default and must be requested explicitly. Like
utcStart, this is calculated at fetch time if requested and may
change due to time zone data changes.
3.2. CalendarEvent/changes CalendarEvent objects MUST NOT have a "method" property as this is
only used when representing iTIP [RFC5546] scheduling messages, not
events in a data store.
Standard "/changes" method as described in [I-D.ietf-jmap-core] 5.1. Attachments
section 5.2
3.3. CalendarEvent/set The Link object, as defined in [I-D.ietf-calext-jscalendar]
Section 4.2.7, with a "rel" property equal to "enclosure" is used to
represent attachments. Instead of mandating an "href" property,
clients may set a "blobId" property instead to reference a blob of
binary data in the account, as per [RFC8620] Section 6.
Standard "/set" method as described in [I-D.ietf-jmap-core] section The server MUST translate this to an embedded "data:" URL [RFC2397]
5.3. when sending the event to a system that cannot access the blob.
Servers that support CalDAV access to the same data are recommended
to expose these files as managed attachments [?@RFC8607].
When an event is created, updated or destroyed, the server MUST also 5.2. Per-user properties
ensure the following:
o Any alerts are scheduled/cancelled correctly. In shared calendars where "shareesActAs" is "self", the following
properties MUST be stored per-user:
o If there is a _participantId_, and the corresponding participant o keywords
has a _role_ of "owner":
* If an event is created/updated: send a REQUEST iMIP email with o color
the event as an ICS attachment to all participants that are not
"you".
* When an event is destroyed, if it is in the future, then email o freeBusyStatus
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.
o If there is a _participantId_, and the corresponding participant o useDefaultAlerts
does not have a _role_ of "owner", and the _scheduleStatus_ is
updated for this participant, send the appropriate iMIP email to
the _replyTo_ address.
3.4. CalendarEvent/copy o alerts
Standard "/copy" method as described in [I-D.ietf-jmap-core] section The user may also modify the above on a per-occurrence basis for
5.4. recurring events; again, these MUST be stored per-user.
3.5. CalendarEvent/query When writing per-user properties, the "updated" property MUST also be
stored just for that user. When fetching the "updated" property, the
value to return is whichever is later of the per-user updated time or
the updated time of the master event.
Standard "/query" method as described in [I-D.ietf-jmap-core] section 5.3. Recurring events
5.5.
3.5.1. Filtering Events may recur, in which case they represent multiple occurrences
or instances. The data store will either contain a single master
event, containing a recurrence rule and/or recurrence overrides; or,
a set of individual instances (when invited to specific occurrences
only).
The client may ask the server to expand recurrences within a specific
time range in "CalendarEvent/query". This will generate synthetic
ids representing individual instances in the requested time range.
The client can fetch and update the objects using these ids and the
server will make the appropriate changes to the master event.
Synthetic ids do not appear in "CalendarEvent/changes" responses;
only the ids of events as actually stored on the server.
If the user is invited to specific instances then later added to the
master event, "CalendarEvent/changes" will show the ids of all the
individual instances being destroyed and the id for the master event
being created.
5.4. CalendarEvent/get
This is a standard "/get" method as described in [RFC8620],
Section 5.1, with three extra arguments:
o *recurrenceOverridesBefore*: "UTCDate|null" If given, only
recurrence overrides with a recurrence id on or after this date
(when translated into UTC) will be returned.
o *recurrenceOverridesAfter*: "UTCDate|null" If given, only
recurrence overrides with a recurrence id before this date (when
translated into UTC) will be returned.
o *reduceParticipants*: "Boolean" (default: false) If true, only
participants with the "owner" role or corresponding to the user's
participant identities will be returned in the "participants"
property of the master event and any recurrence overrides. If
false, all participants will be returned.
A CalendarEvent object is a JSEvent object so may have arbitrary
properties. If the client makes a "CalendarEvent/get" call with a
null or omitted "properties" argument, all properties defined on the
JSEvent object in the store are returned, along with the "id",
"calendarId", and "isDraft" properties. The "utcStart" and "utcEnd"
computed properties are only returned if explicitly requested.
If specific properties are requested from the JSEvent and the
property is not present on the object in the server's store, the
server SHOULD return the default value if known for that property.
An id requested by the server may represent a single instance of a
recurring event if the client asked the server to expand recurrences
in "CalendarEvent/query". In such a case, the server will resolve
any overrides and set the appropriate "start" and "recurrenceId"
properties on the CalendarEvent object returned to the client. The
"recurrenceRule" and "recurrenceOverrides" properties MUST be
returned as null if requested for such an event.
An event with the same uid/recurrenceId may appear in different
accounts. Clients may coalesce the view of such events, but must be
aware that the data may be different in the different accounts due to
per-user properties, difference in permissions etc.
The "privacy" property of a JSEvent object allows the owner to
override how sharees of the calendar see the event. If this is set
to "private", when a sharee fetches the event the server MUST only
return the basic time and metadata properties of the JSEvent object
as specified in [I-D.ietf-calext-jscalendar], Section 4.4.3. If set
to "secret", the server MUST behave as though the event does not
exist for all users other than the owner.
5.5. CalendarEvent/changes
This is a standard "/changes" method as described in [RFC8620],
Section 5.2.
5.6. CalendarEvent/set
This is a standard "/set" method as described in [RFC8620],
Section 5.3, with the following extra argument:
o *sendSchedulingMessages*: "Boolean" (default: true) If true then
any changes to scheduled events will be sent to all the
participants (if the user is an owner of the event) or back to the
owners (otherwise). If false, the changes only affect this
calendar and no scheduling messages will be sent.
For recurring events, an id may represent the master event or a
specific instance. When the id for a specific instance is given, the
server MUST process an update as an update to the recurrence override
for that instance on the master event, and a destroy as removing just
that instance.
Clients MUST NOT send an update/destroy to both the master event and
a specific instance in a single "/set" request; the result of this is
undefined.
Servers MUST enforce the user's permissions as returned in the
"myRights" property of the Calendar object and reject changes with a
"forbidden" SetError if not allowed.
The "privacy" property MUST NOT be set to anything other than
"public" (the default) for events in a calendar that does not belong
to the user (e.g. a shared team calendar). The server MUST reject
this with an _invalidProperties_ SetError.
The server MUST reject attempts to add events with a "participants"
property where none of the participants correspond to one of the
calendar's participant identities with a "forbidden" SetError.
If omitted on create, the server MUST set the following properties to
an appropriate value:
o @type
o uid
o created
o updated
When modifying the event, the server MUST set the following
properties if not explicitly set in the update:
o updated: set to the current time.
o sequence: increment by one, unless only per-user properties (see
Section XXX) were changed.
The "created" property MUST NOT be updated after creation. The
"sequence" property MUST NOT be set to a lower number than its
current value. The "method" property MUST NOT be set. Any attempt
to do these is rejected with a standard "invalidProperties" SetError.
The server does not automatically reset the "partipationStatus" or
"expectReply" properties of a Participant if the event details
change. Clients should either be intelligent about whether the
change necessitates resending RSVP requests, or ask the user whether
to send them.
The server MAY enforce that all events have an owner, for example in
team calendars. If the user tries to create an event without
participants in such a calendar, the server MUST automatically add a
participant with the "owner" role corresponding to one of the user's
"participantIdentities" for the calendar.
When creating an event with participants, or adding participants to
an event that previously did not have participants, the server MUST
set the "replyTo" property of the event if not present. Clients
SHOULD NOT set the replyTo property for events when the user adds
participants; the server is better positioned to add all the methods
it supports to receive replies.
5.6.1. Sending invitations and responses
Unless "sendSchedulingMessages" is false, the server MUST send
appropriate iTIP [RFC5546] scheduling messages after successfuly
creating, updating or destroying a calendar event.
When determining which scheduling messages to send, the server must
first establish whether it is the _source_ of the event. The server
is the source if it will receive messages sent to any of the methods
specified in the "replyTo" property of the event.
Messages are only sent to participants with a "scheduleAgent"
property set to "server" or omitted. If the effective
"scheduleAgent" property is changed:
o to "server" from something else: send messages to this participant
as though the event had just been created.
o from "server" to something else: send messages to this participant
as though the event had just been destroyed.
o any other change: do not send any messages to this participant.
The server may send the scheduling message via any of the methods
defined on the sendTo property of a participant (if the server is the
source) or the replyTo property of the event (otherwise) that it
supports. If no supported methods are available, the server MUST
reject the change with a "noSupportedScheduleMethods" SetError.
If the server is the source of the event it MUST NOT send messages to
any participant corresponding to the participantIdentities of the
calendar it is in.
If sending via iMIP [RFC6047], the server MAY choose to only send
updates it deems "essential" to avoid flooding the recipient's email
with changes they do not care about. For example, changes to the
participationStatus of another participant, or changes to events
solely in the past may be omitted.
5.6.1.1. REQUEST
When the server is the source for the event, a REQUEST message
([RFC5546], Section 3.2.2) is sent to all current participants if:
o The event is being created.
o Any non per-user property (see Section XXX) is updated on the
event (including adding/removing participants), except if just
modifying the recurrenceOverrides such that CANCEL messages are
generated (see the next section).
Note, if the only change is adding an additional instance (not
generated by the event's recurrence rule) to the recurrenceOverrides,
this could be handled via sending an ADD message ([RFC5546],
Section 3.2.4) for the single instance rather than a REQUEST message
for the master. However, for interoperability reasons this is not
recommended due to poor support in the wild for this type of message.
The server MUST ensure participants are only sent information about
recurrence instances they are added to when sending scheduling
messages for recurring events. If the participant is not invited to
the master recurring event but only individual instances, scheduling
messages MUST be sent for just those expanded occurrences
individually. If a participant is invited to a recurring event, but
removed via a recurrence override from a particular instance, any
scheduling messages to this participant MUST return the instance as
"excluded" (if it matches a recurrence rule for the event) or omit
the instance entirely (otherwise).
5.6.1.2. CANCEL
When the server is the source for the event, a CANCEL message
([RFC5546], Section 3.2.5) is sent if:
o A participant is removed from either the master event or a single
instance (the message is only sent to this participant; remaining
participants will get a REQUEST, as described above).
o The event is destroyed.
o An exclusion is added to recurrenceOverrides to remove an instance
generated by the event's recurrence rule.
o An additional instance (not generated by the event's recurrence
rule) is removed from the recurrenceOverrides.
In each of the latter 3 cases, the message is sent to all
participants.
5.6.1.3. REPLY
When the server is _not_ the source for the event, a REPLY message
([RFC5546], Section 3.2.3) is sent for any participant corresponding
to the participantIdentities of the calendar it is in if:
o The "participationStatus" property of the participant is changed.
o The event is destroyed and the participationStatus was not "needs-
action".
o The event is created and the participationStatus is not "needs-
action".
o An exclusion is added to recurrenceOverrides to remove an instance
generated by the event's recurrence rule.
o An exclusion is removed from recurrenceOverrides (this is presumed
to be the client undoing the deletion of a single instance).
o An instance not generated by the event's recurrence rule is
removed from the recurrenceOverrides.
o An instance not generated by the event's recurrence rule is added
to the recurrenceOverrides (this is presumed to be the client
undoing the deletion of a single instance).
A reply is not sent when deleting an event where the current status
is "needs-action" as if a junk calendar event gets added by an
automated system, the user MUST be able to delete the event without
sending a reply.
5.7. CalendarEvent/copy
This is a standard "/copy" method as described in [RFC8620],
Section 5.4.
5.8. CalendarEvent/query
This is a standard "/query" method as described in [RFC8620],
Section 5.5, with two extra arguments:
o *expandRecurrences*: "Boolean" (default: false) If true, the
server will expand any recurring event. If true, the filter MUST
be just a FilterCondition (not a FilterOperator) and MUST include
both a before and after property. This ensures the server is not
asked to return an infinite number of results.
o *timeZone*: "String" The time zone for before/after filter
conditions (default: "Etc/UTC")
If expandRecurrences is true, a separate id will be returned for each
instance of a recurring event that matches the query. Otherwise, a
single id will be returned for matching recurring events that
represents the entire event.
There is no necessary correspondence between the ids of different
instances of the same expanded event.
The following additional error may be returned instead of the
"CalendarEvent/query" response:
"cannotCalculateOccurrences": the server cannot expand a recurrence
required to return the results for this query.
5.8.1. Filtering
A *FilterCondition* object has the following properties: A *FilterCondition* object has the following properties:
o *inCalendars*: "Id[]|null" A list of calendar ids. An event must o *inCalendars*: "Id[]|null" A list of calendar ids. An event must
be in ANY of these calendars to match the condition. be in ANY of these calendars to match the condition.
o *after*: "UTCDate|null" The end of the event, or any recurrence of o *after*: "LocalDate|null" The end of the event, or any recurrence
the event, in UTC time must be after this date to match the of the event, in the time zone given as the timeZone argument,
condition. must be after this date to match the condition.
o *before*: "UTCDate|null" The start of the event, or any recurrence o *before*: "LocalDate|null" The start of the event, or any
of the event, in UTC time must be before this date to match the recurrence of the event, in the time zone given as the timeZone
condition. argument, must be before this date to match the condition.
o *text*: "String|null" Looks for the text in the _title_, o *text*: "String|null" Looks for the text in the _title_,
_description_, _locations_ (matching name/description), or _description_, _locations_ (matching name/description),
_participants_ (matching name/email) properties of the event or _participants_ (matching name/email) and any other textual
any recurrence of the event. properties of the event or any recurrence of the event.
o *title*: "String|null" Looks for the text in the _title_ property o *title*: "String|null" Looks for the text in the _title_ property
of the event, or the overridden _title_ property of a recurrence. of the event, or the overridden _title_ property of a recurrence.
o *description*: "String|null" Looks for the text in the o *description*: "String|null" Looks for the text in the
_description_ property of the event, or the overridden _description_ property of the event, or the overridden
_description_ property of a recurrence. _description_ property of a recurrence.
o *location*: "String|null" Looks for the text in the _locations_ o *location*: "String|null" Looks for the text in the _locations_
property of the event (matching name/description of a location), property of the event (matching name/description of a location),
skipping to change at page 7, line 51 skipping to change at page 29, line 46
o *owner*: "String|null" Looks for the text in the name or email o *owner*: "String|null" Looks for the text in the name or email
fields of a participant in the _participants_ property of the fields of a participant in the _participants_ property of the
event, or the overridden _participants_ property of a recurrence, event, or the overridden _participants_ property of a recurrence,
where the participant has a role of "owner". where the participant has a role of "owner".
o *attendee*: "String|null" Looks for the text in the name or email o *attendee*: "String|null" Looks for the text in the name or email
fields of a participant in the _participants_ property of the fields of a participant in the _participants_ property of the
event, or the overridden _participants_ property of a recurrence, event, or the overridden _participants_ property of a recurrence,
where the participant has a role of "attendee". where the participant has a role of "attendee".
o *participationStatus*: Must match. If owner/attendee condition,
status must be of that participant. Otherwise any.
o *uid*: "String" The uid of the event is exactly the given string.
If expandRecurrences is true, all conditions must match against the
same instance of a recurring event for the instance to match. If
expandRecurrences is false, all conditions must match, but they may
each match any instance of the event.
If zero properties are specified on the FilterCondition, the If zero properties are specified on the FilterCondition, the
condition MUST always evaluate to "true". If multiple properties are condition MUST always evaluate to "true". If multiple properties are
specified, ALL must apply for the condition to be "true" (it is specified, ALL must apply for the condition to be "true" (it is
equivalent to splitting the object into one-property conditions and equivalent to splitting the object into one-property conditions and
making them all the child of an AND filter operator). making them all the child of an AND filter operator).
The exact semantics for matching "String" fields is *deliberately not The exact semantics for matching "String" fields is *deliberately not
defined* to allow for flexibility in indexing implementation, subject defined* to allow for flexibility in indexing implementation, subject
to the following: to the following:
skipping to change at page 8, line 28 skipping to change at page 30, line 33
literal """, "'" and "\" respectively in a phrase. literal """, "'" and "\" respectively in a phrase.
o Outside of a phrase, white-space SHOULD be treated as dividing o Outside of a phrase, white-space SHOULD be treated as dividing
separate tokens that may be searched for separately in the event, separate tokens that may be searched for separately in the event,
but MUST all be present for the event to match the filter. but MUST all be present for the event to match the filter.
o Tokens MAY be matched on a whole-word basis using stemming (so for o Tokens MAY be matched on a whole-word basis using stemming (so for
example a text search for "bus" would match "buses" but not example a text search for "bus" would match "buses" but not
"business"). "business").
3.5.2. Sorting 5.8.2. Sorting
The following properties MUST be supported for sorting: The following properties MUST be supported for sorting:
o start o start
o uid o uid
3.6. CalendarEvent/queryChanges o recurrenceId
Standard "/queryChanges" method as described in [I-D.ietf-jmap-core] The following properties SHOULD be supported for sorting:
section 5.6.
4. Security considerations o created
All security considerations of JMAP ([I-D.ietf-jmap-core]) apply to o updated
this specification. Additional considerations specific to the data
types and functionality introduced by this document are described in
the following subsections.
TODO 5.9. CalendarEvent/queryChanges
5. IANA considerations This is a standard "/queryChanges" method as described in [RFC8620],
Section 5.6.
5.1. JMAP capability registration for "calendars" 5.10. Examples
TODO: Add example of how to get event by uid: query uid=foo and
backref. Return multiple with recurrenceId set (user invited to
specific instances of recurring event).
6. Alerts
Alerts may be specified on events as described in
[I-D.ietf-calext-jscalendar], Section 4.5. If the "useDefaultAlerts"
property is true, the alerts are taken from the Calendar
"defaultAlertsWithTime" or "defaultAlertsWithoutTime" property, as
described in Section XXX. Otherwise, the alerts are taken from the
"alerts" property of the CalendarEvent.
Alerts MUST only be triggered for events in calendars where the user
is subscribed and either the user owns the calendar or the calendar's
"shareesActAs" property is "self".
When an alert with an "email" action is triggered, the server MUST
send an email to the user to notify them of the event. The contents
of the email is implementation specific. Clients MUST NOT perform an
action for these alerts.
When an alert with a "display" action is triggered, clients SHOULD
display an alert in a platform-appropriate manner to the user to
remind them of the event. Clients with a full offline cache of
events may choose to calculate when alerts should trigger locally.
Alternatively, they can subscribe to push events from the server.
6.1. Push events
Servers that support the "urn:ietf:params:jmap:calendars" capability
MUST support registering for the pseudo-type "CalendarAlert" in push
subscriptions and event source connections, as described in
[RFC8620], Sections 7.2 and 7.3.
If requested, a CalendarAlert notification will be pushed whenever an
alert is triggered for the user. For Event Source connections, this
notification is pushed as an event called "calendaralert".
A *CalendarAlert* object has the following properties:
o *@type*: "String" This MUST be the string "CalendarAlert".
o *accountId*: "String" The account id for the calendar in which the
alert triggered.
o *calendarEventId*: "String" The CalendarEvent id for the alert
that triggered.
o *uid*: "String" The uid property of the CalendarEvent for the
alert that triggered.
o *recurrenceId*: "String|null" The recurrenceId for the instance of
the event for which this alert is being triggered, or "null" if
the event is not recurring.
o *alertId*: "String" The id for the alert that triggered.
6.2. Acknowledging an alert
To dismiss an alert, clients set the "acknowledged" property of the
Alert object to the current date-time. When other clients fetch the
CalendarEvent with the updated Alert they SHOULD automatically
dismiss or suppress duplicate alerts (alerts with the same alert id
that triggered on or before this date-time).
Setting the "acknowledged" property MUST NOT create a new recurrence
override. For a recurring calendar object, the "acknowledged"
property of the parent object MUST be updated, unless the alert is
already overridden in the "recurrenceOverrides" property.
6.3. Snoozing an alert
Users may wish to dismiss an alert temporarily and have it come back
after a specific period of time. To do this, clients MUST:
1. Acknowledge the alert as described in Section XXX.
2. Add a new alert with an "AbsoluteTrigger" for the date-time the
alert has been snoozed until. Add a "relatedTo" property to the
new alert, setting the "parent" relation to point to the original
alert. This MUST NOT create a new recurrence override; it is
added to the same "alerts" property that contains the alert being
snoozed.
When acknowledging a snoozed alert (i.e. one with a parent relatedTo
pointing to the original alert), the client SHOULD delete the alert
rather than setting the "acknowledged" property.
7. Calendar Event Notifications
The CalendarEventNotification data type records changes made by
external entities to events in calendars the user is subscribed to.
Notifications are stored in the same Account as the CalendarEvent
that was changed.
Notifications are only created by the server; users cannot create
them directly. Clients SHOULD present the list of notifications to
the user and allow them to dismiss them. To dismiss a notification
you use a standard "/set" call to destroy it.
The server SHOULD create a CalendarEventNotification whenever an
event is added, updated or destroyed by another user or due to
receiving an iTIP [RFC5546] or other scheduling message in a calendar
this user is subscribed to. The server SHOULD NOT create
notifications for events implicitly deleted due to the containing
calendar being deleted.
7.1. Auto-deletion of Notifications
The server MAY limit the maximum number of notifications it will
store for a user. When the limit is reached, any new notification
will cause the previously oldest notification to be automatically
deleted.
The server MAY coalesce events if appropriate, or remove events that
it deems are no longer relevant or after a certain period of time.
The server SHOULD automatically destroy a notification about an event
if the user updates or destroys that event (e.g. if the user sends an
RSVP for the event).
7.2. Object Properties
The *CalendarEventNotification* object has the following properties:
o *id*: "String" The id of the CalendarEventNotification.
o *created*: "UTCDate" The time this notification was created.
o *changedBy*: "Person" Who made the change.
* *name*: "String" The name of the person who made the change.
* *email*: "String" The email of the person who made the change.
* *calendarPrincipalId*: "String|null" The id of the calendar
principal corresponding to the person who made the change, if
any. This will be null if the change was due to receving an
iTIP message.
o *comment*: "String|null" Comment sent along with the change by the
user that made it. (e.g. COMMENT property in an iTIP message).
o *type*: "String" This MUST be one of
* created
* updated
* destroyed
o *calendarEventId*: "String" The id of the CalendarEvent that this
notification is about.
o *isDraft*: "Boolean" (created/updated only) Is this event a draft?
o *event*: "JSEvent" The data before the change (if updated or
destroyed), or the data after creation (if created).
o *eventPatch*: "PatchObject" (updated only) A patch encoding the
change between the data in the event property, and the data after
the update.
To reduce data, if the change only affects a single instance of a
recurring event, the server MAY set the event and eventPatch
properties for the instance; the calendarEventId MUST still be for
the master event.
7.3. CalendarEventNotification/get
This is a standard "/get" method as described in [RFC8620],
Section 5.1.
7.4. CalendarEventNotification/changes
This is a standard "/changes" method as described in [RFC8620],
Section 5.2.
7.5. CalendarEventNotification/set
This is a standard "/changes" method as described in [RFC8620],
Section 5.3.
Only destroy is supported; any attempt to create/update MUST be
rejected with a "forbidden" SetError.
7.6. CalendarEventNotification/query
This is a standard "/query" method as described in [RFC8620],
Section 5.5.
7.6.1. Filtering
A *FilterCondition* object has the following properties:
o *after*: "UTCDate|null" The creation date must be on or after this
date to match the condition.
o *before*: "UTCDate|null" The creation date must be before this
date to match the condition.
o *type*: "String" The type property must be the same to match the
condition.
o *calendarEventIds*: "Id[]|null" A list of event ids. The
calendarEventId property of the notification must be in this list
to match the condition.
7.6.2. Sorting
The "created" property MUST be supported for sorting.
7.7. CalendarEventNotification/queryChanges
This is a standard "/queryChanges" method as described in [RFC8620],
Section 5.6.
8. Security Considerations
All security considerations of JMAP [RFC8620] and JSCalendar
[I-D.ietf-calext-jscalendar] apply to this specification. Additional
considerations specific to the data types and functionality
introduced by this document are described in the following
subsections.
8.1. Denial-of-service Expanding Recurrences
Recurrence rules can be crafted to occur as frequently as every
second. Servers MUST be careful to not allow resources to be
exhausted when expanding. Equally, rules can be generated that never
create any occurrences at all. Servers MUST be careful to limit the
work spent iterating in search of the next occurrence.
8.2. Privacy
TODO.
9. IANA Considerations
9.1. JMAP Capability Registration for "calendars"
IANA will register the "calendars" JMAP Capability as follows: IANA will register the "calendars" JMAP Capability as follows:
Capability Name: "urn:ietf:params:jmap:calendars" Capability Name: "urn:ietf:params:jmap:calendars"
Specification document: this document Specification document: this document
Intended use: common Intended use: common
Change Controller: IETF Change Controller: IETF
Security and privacy considerations: this document, section TODO Security and privacy considerations: this document, Section XXX
6. Normative References 9.2. Reservation of JMAP attributes in JSCalendar Property registry
TODO.
10. References
10.1. Normative References
[I-D.ietf-calext-jscalendar] [I-D.ietf-calext-jscalendar]
Jenkins, N. and R. Stepanek, "JSCalendar: A JSON Jenkins, N. and R. Stepanek, "JSCalendar: A JSON
representation of calendar data", draft-ietf-calext- representation of calendar data", draft-ietf-calext-
jscalendar-12 (work in progress), March 2019. jscalendar-20 (work in progress), October 2019.
[I-D.ietf-jmap-core]
Jenkins, N. and C. Newman, "JSON Meta Application
Protocol", draft-ietf-jmap-core-17 (work in progress),
March 2019.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997, DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>. <https://www.rfc-editor.org/info/rfc2119>.
[RFC2397] Masinter, L., "The "data" URL scheme", RFC 2397,
DOI 10.17487/RFC2397, August 1998,
<https://www.rfc-editor.org/info/rfc2397>.
[RFC5546] Daboo, C., Ed., "iCalendar Transport-Independent
Interoperability Protocol (iTIP)", RFC 5546,
DOI 10.17487/RFC5546, December 2009,
<https://www.rfc-editor.org/info/rfc5546>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>. May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application
Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July
2019, <https://www.rfc-editor.org/info/rfc8620>.
10.2. Informative References
[RFC4791] Daboo, C., Desruisseaux, B., and L. Dusseault,
"Calendaring Extensions to WebDAV (CalDAV)", RFC 4791,
DOI 10.17487/RFC4791, March 2007,
<https://www.rfc-editor.org/info/rfc4791>.
[RFC6047] Melnikov, A., Ed., "iCalendar Message-Based
Interoperability Protocol (iMIP)", RFC 6047,
DOI 10.17487/RFC6047, December 2010,
<https://www.rfc-editor.org/info/rfc6047>.
Authors' Addresses Authors' Addresses
Neil Jenkins Neil Jenkins
FastMail Fastmail
PO Box 234, Collins St West PO Box 234, Collins St West
Melbourne VIC 8007 Melbourne VIC 8007
Australia Australia
Email: neilj@fastmailteam.com Email: neilj@fastmailteam.com
URI: https://www.fastmail.com URI: https://www.fastmail.com
Michael Douglass Michael Douglass
Spherical Cow Group Spherical Cow Group
226 3rd Street 226 3rd Street
Troy NY 12180 Troy NY 12180
United States of America United States of America
Email: mdouglass@sphericalcowgroup.com Email: mdouglass@sphericalcowgroup.com
URI: http://sphericalcowgroup.com URI: http://sphericalcowgroup.com
 End of changes. 83 change blocks. 
192 lines changed or deleted 1499 lines changed or added

This html diff was produced by rfcdiff 1.47. The latest version is available from http://tools.ietf.org/tools/rfcdiff/