rfc9610.original | rfc9610.txt | |||
---|---|---|---|---|
JMAP N.M. Jenkins, Ed. | Internet Engineering Task Force (IETF) N. Jenkins, Ed. | |||
Internet-Draft Fastmail | Request for Comments: 9610 Fastmail | |||
Intended status: Standards Track 7 June 2024 | Category: Standards Track December 2024 | |||
Expires: 9 December 2024 | ISSN: 2070-1721 | |||
JMAP for Contacts | JSON Meta Application Protocol (JMAP) for Contacts | |||
draft-ietf-jmap-contacts-10 | ||||
Abstract | Abstract | |||
This document specifies a data model for synchronising contacts data | This document specifies a data model for synchronising contact data | |||
with a server using JMAP. | with a server using the JSON Meta Application Protocol (JMAP). | |||
Status of This Memo | Status of This Memo | |||
This Internet-Draft is submitted in full conformance with the | This is an Internet Standards Track document. | |||
provisions of BCP 78 and BCP 79. | ||||
Internet-Drafts are working documents of the Internet Engineering | ||||
Task Force (IETF). Note that other groups may also distribute | ||||
working documents as Internet-Drafts. The list of current Internet- | ||||
Drafts is at https://datatracker.ietf.org/drafts/current/. | ||||
Internet-Drafts are draft documents valid for a maximum of six months | This document is a product of the Internet Engineering Task Force | |||
and may be updated, replaced, or obsoleted by other documents at any | (IETF). It represents the consensus of the IETF community. It has | |||
time. It is inappropriate to use Internet-Drafts as reference | received public review and has been approved for publication by the | |||
material or to cite them other than as "work in progress." | Internet Engineering Steering Group (IESG). Further information on | |||
Internet Standards is available in Section 2 of RFC 7841. | ||||
This Internet-Draft will expire on 9 December 2024. | Information about the current status of this document, any errata, | |||
and how to provide feedback on it may be obtained at | ||||
https://www.rfc-editor.org/info/rfc9610. | ||||
Copyright Notice | Copyright Notice | |||
Copyright (c) 2024 IETF Trust and the persons identified as the | Copyright (c) 2024 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 (https://trustee.ietf.org/ | Provisions Relating to IETF Documents | |||
license-info) in effect on the date of publication of this document. | (https://trustee.ietf.org/license-info) in effect on the date of | |||
Please review these documents carefully, as they describe your rights | publication of this document. Please review these documents | |||
and restrictions with respect to this document. Code Components | carefully, as they describe your rights and restrictions with respect | |||
extracted from this document must include Revised BSD License text as | to this document. Code Components extracted from this document must | |||
described in Section 4.e of the Trust Legal Provisions and are | include Revised BSD License text as described in Section 4.e of the | |||
provided without warranty as described in the Revised BSD License. | Trust Legal Provisions and are provided without warranty as described | |||
in the Revised BSD License. | ||||
Table of Contents | Table of Contents | |||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 | 1. Introduction | |||
1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3 | 1.1. Notational Conventions | |||
1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 | 1.2. Terminology | |||
1.3. Data Model Overview . . . . . . . . . . . . . . . . . . . 3 | 1.3. Data Model Overview | |||
1.4. Addition to the Capabilities Object . . . . . . . . . . . 3 | 1.4. Addition to the Capabilities Object | |||
1.4.1. urn:ietf:params:jmap:contacts . . . . . . . . . . . . 3 | 1.4.1. urn:ietf:params:jmap:contacts | |||
2. AddressBooks . . . . . . . . . . . . . . . . . . . . . . . . 4 | 2. AddressBooks | |||
2.1. AddressBook/get . . . . . . . . . . . . . . . . . . . . . 6 | 2.1. AddressBook/get | |||
2.2. AddressBook/changes . . . . . . . . . . . . . . . . . . . 6 | 2.2. AddressBook/changes | |||
2.3. AddressBook/set . . . . . . . . . . . . . . . . . . . . . 6 | 2.3. AddressBook/set | |||
3. ContactCards . . . . . . . . . . . . . . . . . . . . . . . . 7 | 3. ContactCards | |||
3.1. ContactCard/get . . . . . . . . . . . . . . . . . . . . . 8 | 3.1. ContactCard/get | |||
3.2. ContactCard/changes . . . . . . . . . . . . . . . . . . . 8 | 3.2. ContactCard/changes | |||
3.3. ContactCard/query . . . . . . . . . . . . . . . . . . . . 8 | 3.3. ContactCard/query | |||
3.3.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 8 | 3.3.1. Filtering | |||
3.3.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 11 | 3.3.2. Sorting | |||
3.4. ContactCard/queryChanges . . . . . . . . . . . . . . . . 11 | 3.4. ContactCard/queryChanges | |||
3.5. ContactCard/set . . . . . . . . . . . . . . . . . . . . . 11 | 3.5. ContactCard/set | |||
3.6. ContactCard/copy . . . . . . . . . . . . . . . . . . . . 11 | 3.6. ContactCard/copy | |||
4. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 12 | 4. Examples | |||
4.1. Fetching initial data . . . . . . . . . . . . . . . . . . 12 | 4.1. Fetching Initial Data | |||
4.2. Changing the default address book . . . . . . . . . . . . 14 | 4.2. Changing the Default Address Book | |||
5. Internationalisation Considerations . . . . . . . . . . . . . 14 | 5. Internationalisation Considerations | |||
6. Security Considerations . . . . . . . . . . . . . . . . . . . 15 | 6. Security Considerations | |||
7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 15 | 7. IANA Considerations | |||
7.1. JMAP capability registration for "contacts" . . . . . . . 15 | 7.1. JMAP Capability Registration for "contacts" | |||
7.2. JMAP Data Type Registration for "AddressBook" . . . . . . 15 | 7.2. JMAP Data Type Registration for "AddressBook" | |||
7.3. JMAP Data Type Registration for "ContactCard" . . . . . . 16 | 7.3. JMAP Data Type Registration for "ContactCard" | |||
7.4. JMAP Error Codes Registry . . . . . . . . . . . . . . . . 16 | 7.4. JMAP Error Codes Registry | |||
7.4.1. addressBookHasContents . . . . . . . . . . . . . . . 16 | 7.4.1. addressBookHasContents | |||
7.5. JSContact Property Registrations . . . . . . . . . . . . 16 | 7.5. JSContact Property Registrations | |||
7.5.1. id . . . . . . . . . . . . . . . . . . . . . . . . . 16 | 7.5.1. id | |||
7.5.2. addressBookIds . . . . . . . . . . . . . . . . . . . 17 | 7.5.2. addressBookIds | |||
7.5.3. blobId . . . . . . . . . . . . . . . . . . . . . . . 17 | 7.5.3. blobId | |||
8. Normative References . . . . . . . . . . . . . . . . . . . . 17 | 8. References | |||
9. Informative References . . . . . . . . . . . . . . . . . . . 18 | 8.1. Normative References | |||
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 18 | 8.2. Informative References | |||
Author's Address | ||||
1. Introduction | 1. Introduction | |||
JMAP ([RFC8620] JSON Meta Application Protocol) is a generic protocol | The JSON Meta Application Protocol (JMAP) [RFC8620] is a generic | |||
for synchronising data, such as mail, calendars or contacts, between | protocol for synchronising data, such as mail, calendars, or | |||
a client and a server. It is optimised for mobile and web | contacts, between a client and a server. It is optimised for mobile | |||
environments, and aims to provide a consistent interface to different | and web environments and aims to provide a consistent interface to | |||
data types. | different data types. | |||
This specification defines a data model for synchronising contacts | This specification defines a data model for synchronising contacts | |||
between a client and a server using JMAP. | between a client and a server using JMAP. | |||
1.1. Notational Conventions | 1.1. 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 | |||
14 [RFC2119] [RFC8174] when, and only when, they appear in all | BCP 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 [RFC8620]. The | follow the conventions established in Section 1.1 of [RFC8620]. The | |||
Id, UnsignedInt, and UTCDate data types defined in Sections 1.2, 1.3, | Id, UnsignedInt, and UTCDate data types defined in Sections 1.2, 1.3, | |||
and 1.4 of [RFC8620] are also used in this document. | and 1.4 of [RFC8620] are also used in this document. | |||
1.2. Terminology | 1.2. Terminology | |||
The same terminology is used in this document as in the core JMAP | The same terminology used in the core JMAP specification (see | |||
specification, see [RFC8620], Section 1.6. | Section 1.6 of [RFC8620]) is also used in this document. | |||
The terms AddressBook and ContactCard (with these specific | The terms AddressBook and ContactCard (with these specific | |||
capitalizations) are used to refer to the data types defined in this | capitalizations) are used to refer to the data types defined in this | |||
document and instances of those data types. | document and instances of those data types. | |||
1.3. Data Model Overview | 1.3. Data Model Overview | |||
An Account (see [RFC8620], Section 1.6.2) with support for the | An Account (see Section 1.6.2 of [RFC8620]) with support for the | |||
contacts data model contains zero or more AddressBook objects, which | contact data model contains zero or more AddressBook objects, which | |||
is a named collection of zero or more ContactCards. A ContactCard is | is a named collection of zero or more ContactCards. A ContactCard is | |||
a representation of a person, company, or other entity, or a group of | a representation of a person, company, entity, or a group of such | |||
such entities, in JSContact Card format, as defined in Section 2 of | entities in JSContact Card format, as defined in Section 2 of | |||
[RFC9553]. Each ContactCard belongs to one or more AddressBooks. | [RFC9553]. Each ContactCard belongs to one or more AddressBooks. | |||
In servers with support for JMAP Sharing [I-D.ietf-jmap-sharing], | In servers with support for JMAP Sharing [RFC9670], users may see and | |||
users may see and configure sharing of contact data with others. | configure sharing of contact data with others. Sharing permissions | |||
Sharing permissions are managed per AddressBook. | are managed per AddressBook. | |||
1.4. Addition to the Capabilities Object | 1.4. Addition to the Capabilities Object | |||
The capabilities object is returned as part of the JMAP Session | The capabilities object is returned as part of the JMAP Session | |||
object; see [RFC8620], Section 2. This document defines one | object; see Section 2 of [RFC8620]. This document defines one | |||
additional capability URI. | additional capability URI. | |||
1.4.1. urn:ietf:params:jmap:contacts | 1.4.1. urn:ietf:params:jmap:contacts | |||
This represents support for the AddressBook and ContactCard data | This represents support for the AddressBook and ContactCard data | |||
types and associated API methods. The value of this property in the | types and associated API methods. The value of this property in the | |||
JMAP Session capabilities property is an empty object. | JMAP Session "capabilities" property is an empty object. | |||
The value of this property in an account's accountCapabilities | The value of this property in an account's "accountCapabilities" | |||
property is an object that MUST contain the following information on | property is an object that MUST contain the following information on | |||
server capabilities and permissions for that account: | server capabilities and permissions for that account: | |||
* *maxAddressBooksPerCard*: UnsignedInt|null | *maxAddressBooksPerCard*: UnsignedInt|null | |||
The maximum number of AddressBooks (see Section 2) that can be | The maximum number of AddressBooks (see Section 2) that can be | |||
assigned to a single ContactCard object (see Section 3). This | assigned to a single ContactCard object (see Section 3). This | |||
MUST be an integer >= 1, or null for no limit (or rather, the | MUST be an integer >= 1, or null for no limit (or rather, the | |||
limit is always the number of AddressBooks in the account). | limit is always the number of AddressBooks in the account). | |||
* *mayCreateAddressBook*: Boolean | ||||
*mayCreateAddressBook*: Boolean | ||||
The user may create an AddressBook in this account if, and only | The user may create an AddressBook in this account if, and only | |||
if, this is true. | if, this is true. | |||
2. AddressBooks | 2. AddressBooks | |||
An AddressBook is a named collection of ContactCards. All | An AddressBook is a named collection of ContactCards. All | |||
ContactCards are associated with one or more AddressBook. | ContactCards are associated with one or more AddressBooks. | |||
A *AddressBook* object has the following properties: | ||||
* *id*: Id (immutable; server-set) | An *AddressBook* object has the following properties: | |||
*id*: Id (immutable; server-set) | ||||
The id of the AddressBook. | The id of the AddressBook. | |||
* *name*: String | *name*: String | |||
The user-visible name of the AddressBook. This MUST NOT be the | The user-visible name of the AddressBook. This MUST NOT be the | |||
empty string and MUST NOT be greater than 255 octets in size when | empty string and MUST NOT be greater than 255 octets in size when | |||
encoded as UTF-8. | encoded as UTF-8. | |||
* *description*: String|null (default: null) | *description*: String|null (default: null) | |||
An optional long-form description of the AddressBook that provides | ||||
An optional longer-form description of the AddressBook, to provide | ||||
context in shared environments where users need more than just the | context in shared environments where users need more than just the | |||
name. | name. | |||
* *sortOrder*: UnsignedInt (default: 0) | *sortOrder*: UnsignedInt (default: 0) | |||
Defines the sort order of AddressBooks when presented in the | Defines the sort order of AddressBooks when presented in the | |||
client's UI, so it is consistent between devices. The number MUST | client's UI so it is consistent between devices. The number MUST | |||
be an integer in the range 0 <= sortOrder < 2^(31.) | be an integer in the range 0 <= sortOrder < 2^31. | |||
An AddressBook with a lower order is to be displayed before a | An AddressBook with a lower order is to be displayed before a | |||
AddressBook with a higher order in any list of AddressBooks in the | AddressBook with a higher order in any list of AddressBooks in the | |||
client's UI. AddressBooks with equal order should be sorted in | client's UI. AddressBooks with equal order should be sorted in | |||
alphabetical order by name. The sorting should take into account | alphabetical order by name. The sorting should take into account | |||
locale-specific character order convention. | locale-specific character order convention. | |||
* *isDefault*: Boolean (server-set) | *isDefault*: Boolean (server-set) | |||
This SHOULD be true for exactly one AddressBook in any account and | ||||
This SHOULD be true for exactly one AddressBook in any account, | MUST NOT be true for more than one AddressBook within an account. | |||
and MUST NOT be true for more than one AddressBook within an | The default AddressBook should be used by clients whenever they | |||
account. The default AddressBook should be used by clients | need to choose an AddressBook for the user within this account and | |||
whenever they need to choose an AddressBook for the user within | they do not have any other information on which to make a choice. | |||
this account, and they do not have any other information on which | For example, if the user creates a new contact card, the client | |||
to make a choice. For example, if the user creates a new contact | may automatically set the card as belonging to the default | |||
card, the client may automatically set the card as belonging to | AddressBook from the user's primary account. | |||
the default AddressBook from the user's primary account. | ||||
* *isSubscribed*: Boolean | ||||
*isSubscribed*: Boolean | ||||
True if the user has indicated they wish to see this AddressBook | True if the user has indicated they wish to see this AddressBook | |||
in their client. This SHOULD default to false for AddressBooks in | in their client. This SHOULD default to false for AddressBooks in | |||
shared accounts the user has access to and true for any new | shared accounts that the user has access to and true for any new | |||
AddressBooks created by the user themself. | AddressBooks created by the user themself. | |||
If false, the AddressBook and its contents SHOULD only be | If false, the AddressBook and its contents SHOULD only be | |||
displayed when the user explicitly requests it or to offer it for | displayed when the user explicitly requests it. The UI may offer | |||
the user to subscribe to. | to the user the option of subscribing to it. | |||
* *shareWith*: Id[AddressBookRights]|null (default: null) | ||||
A map of Principal (Section 2 of [I-D.ietf-jmap-sharing]) id to | ||||
rights for principals this AddressBook is shared with. The | ||||
principal to which this AddressBook belongs MUST NOT be in this | ||||
set. This is null if the AddressBook is not shared with anyone, | ||||
or the server does not support [I-D.ietf-jmap-sharing]. The value | ||||
may be modified only if the user has the mayShare right. The | ||||
account id for the principals may be found in the | ||||
urn:ietf:params:jmap:principals:owner capability of the Account to | ||||
which the AddressBook belongs. | ||||
* *myRights*: AddressBookRights (server-set) | *shareWith*: Id[AddressBookRights]|null (default: null) | |||
A map of the Principal id (Section 2 of [RFC9670]) to rights for | ||||
Principals this AddressBook is shared with. The Principal to | ||||
which this AddressBook belongs MUST NOT be in this set. This is | ||||
null if the AddressBook is not shared with anyone or if the server | ||||
does not support [RFC9670]. The value may be modified only if the | ||||
user has the "mayShare" right. The account id for the Principals | ||||
may be found in the urn:ietf:params:jmap:principals:owner | ||||
capability of the Account to which the AddressBook belongs. | ||||
*myRights*: AddressBookRights (server-set) | ||||
The set of access rights the user has in relation to this | The set of access rights the user has in relation to this | |||
AddressBook. | AddressBook. | |||
An *AddressBookRights* object has the following properties: | An *AddressBookRights* object has the following properties: | |||
* *mayRead*: Boolean | *mayRead*: Boolean | |||
The user may fetch the ContactCards in this AddressBook. | The user may fetch the ContactCards in this AddressBook. | |||
* *mayWrite*: Boolean | ||||
The user may create, modify or destroy all ContactCards in this | *mayWrite*: Boolean | |||
The user may create, modify, or destroy all ContactCards in this | ||||
AddressBook, or move them to or from this AddressBook. | AddressBook, or move them to or from this AddressBook. | |||
* *mayShare*: Boolean | ||||
*mayShare*: Boolean | ||||
The user may modify the "shareWith" property for this AddressBook. | The user may modify the "shareWith" property for this AddressBook. | |||
* *mayDelete*: Boolean | *mayDelete*: Boolean | |||
The user may delete the AddressBook itself. | The user may delete the AddressBook itself. | |||
2.1. AddressBook/get | 2.1. AddressBook/get | |||
This is a standard "/get" method as described in [RFC8620], | This is a standard "/get" method as described in Section 5.1 of | |||
Section 5.1. The _ids_ argument may be null to fetch all at once. | [RFC8620]. The "ids" argument may be null to fetch all at once. | |||
2.2. AddressBook/changes | 2.2. AddressBook/changes | |||
This is a standard "/changes" method as described in [RFC8620], | This is a standard "/changes" method as described in Section 5.2 of | |||
Section 5.2. | [RFC8620]. | |||
2.3. AddressBook/set | 2.3. AddressBook/set | |||
This is a standard "/set" method as described in [RFC8620], | This is a standard "/set" method as described in Section 5.3 of | |||
Section 5.3 but with the following additional request argument: | [RFC8620], but with the following additional request arguments: | |||
* *onDestroyRemoveContents*: Boolean (default: false) | ||||
*onDestroyRemoveContents*: Boolean (default: false) | ||||
If false, any attempt to destroy an AddressBook that still has a | If false, any attempt to destroy an AddressBook that still has a | |||
ContactCard in it will be rejected with an addressBookHasContents | ContactCard in it will be rejected with an | |||
SetError. If true, any ContactCard that is in the AddressBook | "addressBookHasContents" SetError. If true, any ContactCard that | |||
will be removed from it, and if such a ContactCard does not belong | is in the AddressBook will be removed from it, and if such a | |||
to any other AddressBook it will be destroyed. | ContactCard does not belong to any other AddressBook, it will be | |||
destroyed. | ||||
* *onSuccessSetIsDefault*: Id|null | ||||
If an id is given, and all creates, updates and destroys (if any) | *onSuccessSetIsDefault*: Id|null | |||
If an id is given, and all creates, updates, and destroys (if any) | ||||
succeed without error, the server will try to set this AddressBook | succeed without error, the server will try to set this AddressBook | |||
as the default. (For references to AddressBook creations, this is | as the default. (For references to AddressBook creations, this is | |||
equivalent to a creation-reference, so the id will be the creation | equivalent to a creation-reference, so the id will be the creation | |||
id prefixed with a "#".) | id prefixed with a "#".) | |||
If the id is not found, or the change is not permitted by the server | If the id is not found or if the change is not permitted by the | |||
for policy reasons, it MUST be ignored and the currently default | server for policy reasons, it MUST be ignored and the current default | |||
AddressBook (if any) will remain as such. No error is returned to | AddressBook (if any) will remain as such. No error is returned to | |||
the client in this case. | the client in this case. | |||
As per [RFC8620], Section 5.3, if the default is successfully | As per Section 5.3 of [RFC8620], if the default AddressBook is | |||
changed, any changed objects MUST be reported in either the "created" | successfully changed, any changed objects MUST be reported in either | |||
or "updated" argument in the response as appropriate, with the | the "created" or "updated" argument in the response as appropriate, | |||
server-set value included. | with the server-set value included. | |||
The "shareWith" property may only be set by users that have the | The "shareWith" property may only be set by users that have the | |||
mayShare right. When modifying the shareWith property, the user | "mayShare" right. When modifying the "shareWith" property, the user | |||
cannot give a right to a principal if the principal did not already | cannot give a right to a Principal if the Principal did not already | |||
have that right and the user making the change also does not have | have that right and the user making the change also does not have | |||
that right. Any attempt to do so MUST be rejected with a forbidden | that right. Any attempt to do so MUST be rejected with a "forbidden" | |||
SetError. | SetError. | |||
Users can subscribe or unsubscribe to an AddressBook by setting the | Users can subscribe or unsubscribe to an AddressBook by setting the | |||
"isSubscribed" property. The server MAY forbid users from | "isSubscribed" property. The server MAY forbid users from | |||
subscribing to certain AddressBooks even though they have permission | subscribing to certain AddressBooks even though they have permission | |||
to see them, rejecting the update with a forbidden SetError. | to see them, rejecting the update with a "forbidden" SetError. | |||
The following extra SetError type is defined: | ||||
For "destroy": | The following extra SetError type is defined for "destroy": | |||
* *addressBookHasContents*: The AddressBook has at least one | *addressBookHasContents*: The AddressBook has at least one | |||
ContactCard assigned to it, and the "onDestroyRemoveContents" | ContactCard assigned to it and the "onDestroyRemoveContents" | |||
argument was false. | argument was false. | |||
3. ContactCards | 3. ContactCards | |||
A *ContactCard* object contains information about a person, company, | A *ContactCard* object contains information about a person, company, | |||
or other entity, or represents a group of such entities. It is a | or other entity, or represents a group of such entities. It is a | |||
JSContact Card object, as defined in Section 2 of [RFC9553], with the | JSContact Card object as defined in Section 2 of [RFC9553] with the | |||
following additional properties: | following additional properties: | |||
* *id*: Id (immutable; server-set) | *id*: Id (immutable; server-set) | |||
The id of the ContactCard. The id property MAY be different to | The id of the ContactCard. The "id" property MAY be different to | |||
the ContactCard's "uid" property (as defined in Section 2.1.9 of | the ContactCard's "uid" property (as defined in Section 2.1.9 of | |||
[RFC9553]). However there MUST NOT be more than one ContactCard | [RFC9553]). However, there MUST NOT be more than one ContactCard | |||
with the same "uid" in an Account. | with the same uid in an Account. | |||
* *addressBookIds*: Id[Boolean] | ||||
The set of AddressBook ids this ContactCard belongs to. A card | *addressBookIds*: Id[Boolean] | |||
MUST belong to at least one AddressBook at all times (until it is | The set of AddressBook ids that this ContactCard belongs to. A | |||
destroyed). The set is represented as an object, with each key | card MUST belong to at least one AddressBook at all times (until | |||
being an AddressBook id. The value for each key in the object | it is destroyed). The set is represented as an object, with each | |||
key being an AddressBook id. The value for each key in the object | ||||
MUST be true. | MUST be true. | |||
For any Media object in the card (see Section 2.6.4 of [RFC9553]), a | For any Media object in the card (see Section 2.6.4 of [RFC9553]), a | |||
new property is defined: | new property is defined: | |||
* *blobId*: Id | *blobId*: Id | |||
An id for the Blob representing the binary contents of the | An id for the Blob representing the binary contents of the | |||
resource. | resource. | |||
When returning ContactCards, any Media with a URI that uses the data | When returning ContactCards, any Media with a URI that uses the | |||
URL scheme ([RFC2397]) SHOULD return a blobId property and omit the | "data:" URL scheme [RFC2397] SHOULD return a "blobId" property and | |||
uri property, as this lets clients load the (potentially large) image | omit the "uri" property, as this lets clients load the (potentially | |||
file only when needed, and avoids the overhead of Base64 encoding. | large) image file only when needed and avoids the overhead of Base64 | |||
The "mediaType" property MUST also be set. Similarly, when creating | encoding. The "mediaType" property MUST also be set. Similarly, | |||
or updating a ContactCard, clients MAY send a blobId instead of the | when creating or updating a ContactCard, clients MAY send a "blobId" | |||
uri property for a Media object. | instead of the "uri" property for a Media object. | |||
A contact card with a "kind" property equal to "group" represents a | A contact card with a "kind" property equal to "group" represents a | |||
group of contacts. Clients often present these separately from other | group of contacts. Clients often present these separately from other | |||
contact cards. The "members" property, as defined in Section 2.1.6 | contact cards. The "members" property, as defined in Section 2.1.6 | |||
of [RFC9553], contains a set of UIDs (as defined in Section 2.1.9 of | of [RFC9553], contains a set of uids (as defined in Section 2.1.9 of | |||
[RFC9553]) for other contacts that are the members of this group. | [RFC9553]) for other contacts that are the members of this group. | |||
Clients should consider the group to contain any ContactCard with a | Clients should consider the group to contain any ContactCard with a | |||
matching UID, from any account they have access to with support for | matching uid from any account they have access to that has support | |||
the urn:ietf:params:jmap:contacts capability. UIDs that cannot be | for the urn:ietf:params:jmap:contacts capability. Any uid that | |||
found SHOULD be ignored but preserved. For example, suppose a user | cannot be found SHOULD be ignored but preserved. For example, | |||
adds contacts from a shared address book to their private group, then | suppose a user adds contacts from a shared address book to their | |||
temporarily loses access to this address book. The UIDs cannot be | private group, then temporarily loses access to this address book. | |||
resolved so the contacts will disappear from the group. However, if | The uids cannot be resolved, so the contacts will disappear from the | |||
they are given permission to access the data again the UIDs will be | group. However, if they are given permission to access the data | |||
found and the contacts will reappear. | again, the uids will be found and the contacts will reappear. | |||
3.1. ContactCard/get | 3.1. ContactCard/get | |||
This is a standard "/get" method as described in [RFC8620], | This is a standard "/get" method as described in Section 5.1 of | |||
Section 5.1. | [RFC8620]. | |||
3.2. ContactCard/changes | 3.2. ContactCard/changes | |||
This is a standard "/changes" method as described in [RFC8620], | This is a standard "/changes" method as described in Section 5.2 of | |||
Section 5.2. | [RFC8620]. | |||
3.3. ContactCard/query | 3.3. ContactCard/query | |||
This is a standard "/query" method as described in [RFC8620], | This is a standard "/query" method as described in Section 5.5 of | |||
Section 5.5. | [RFC8620]. | |||
3.3.1. Filtering | 3.3.1. Filtering | |||
A *FilterCondition* object has the following properties, any of which | A *FilterCondition* object has the following properties, any of which | |||
may be omitted: | may be omitted: | |||
* *inAddressBook*: Id | *inAddressBook*: Id | |||
An AddressBook id. A card must be in this address book to match | An AddressBook id. A card must be in this address book to match | |||
the condition. | the condition. | |||
* *uid*: String | ||||
*uid*: String | ||||
A card must have this string exactly as its uid (as defined in | A card must have this string exactly as its uid (as defined in | |||
Section 2.1.9 of [RFC9553]) to match. | Section 2.1.9 of [RFC9553]) to match. | |||
* *hasMember*: String | ||||
*hasMember*: String | ||||
A card must have a "members" property (as defined in Section 2.1.6 | A card must have a "members" property (as defined in Section 2.1.6 | |||
of [RFC9553]) that contains this string as one of the uids in the | of [RFC9553]) that contains this string as one of the uids in the | |||
set to match. | set to match. | |||
* *kind*: String | ||||
A card must have a kind property (as defined in Section 2.1.4 of | *kind*: String | |||
A card must have a "kind" property (as defined in Section 2.1.4 of | ||||
[RFC9553]) that equals this string exactly to match. | [RFC9553]) that equals this string exactly to match. | |||
* *createdBefore*: UTCDate | ||||
*createdBefore*: UTCDate | ||||
The "created" date-time of the ContactCard (as defined in | The "created" date-time of the ContactCard (as defined in | |||
Section 2.1.3 of [RFC9553]) must be before this date-time to match | Section 2.1.3 of [RFC9553]) must be before this date-time to match | |||
the condition. | the condition. | |||
* *createdAfter*: UTCDate | ||||
*createdAfter*: UTCDate | ||||
The "created" date-time of the ContactCard (as defined in | The "created" date-time of the ContactCard (as defined in | |||
Section 2.1.3 of [RFC9553]) must be the same or after this date- | Section 2.1.3 of [RFC9553]) must be the same or after this date- | |||
time to match the condition. | time to match the condition. | |||
* *updatedBefore*: UTCDate | ||||
*updatedBefore*: UTCDate | ||||
The "updated" date-time of the ContactCard (as defined in | The "updated" date-time of the ContactCard (as defined in | |||
Section 2.1.10 of [RFC9553]) must be before this date-time to | Section 2.1.10 of [RFC9553]) must be before this date-time to | |||
match the condition. | match the condition. | |||
* *updatedAfter*: UTCDate | ||||
*updatedAfter*: UTCDate | ||||
The "updated" date-time of the ContactCard (as defined in | The "updated" date-time of the ContactCard (as defined in | |||
Section 2.1.10 of [RFC9553]) must be the same or after this date- | Section 2.1.10 of [RFC9553]) must be the same or after this date- | |||
time to match the condition. | time to match the condition. | |||
* *text*: String | ||||
*text*: String | ||||
A card matches this condition if the text matches with text in the | A card matches this condition if the text matches with text in the | |||
card. | card. | |||
* *name*: String | ||||
*name*: String | ||||
A card matches this condition if the value of any NameComponent in | A card matches this condition if the value of any NameComponent in | |||
the "name" property, or the "full" property in the "name" property | the "name" property or the "full" property in the "name" property | |||
of the card, (as defined in Section 2.2.1.2 of [RFC9553]) matches | of the card (as defined in Section 2.2.1.2 of [RFC9553]) matches | |||
the value. | the value. | |||
* *name/given*: String | ||||
*name/given*: String | ||||
A card matches this condition if the value of a NameComponent with | A card matches this condition if the value of a NameComponent with | |||
kind "given" inside the "name" property of the card (as defined in | kind "given" inside the "name" property of the card (as defined in | |||
Section 2.2.1.2 of [RFC9553]) matches the value. | Section 2.2.1.2 of [RFC9553]) matches the value. | |||
* *name/surname*: String | ||||
*name/surname*: String | ||||
A card matches this condition if the value of a NameComponent with | A card matches this condition if the value of a NameComponent with | |||
kind "surname" inside the "name" property of the card (as defined | kind "surname" inside the "name" property of the card (as defined | |||
in Section 2.2.1.2 of [RFC9553]) matches the value. | in Section 2.2.1.2 of [RFC9553]) matches the value. | |||
* *name/surname2*: String | ||||
*name/surname2*: String | ||||
A card matches this condition if the value of a NameComponent with | A card matches this condition if the value of a NameComponent with | |||
kind "surname2" inside the "name" property of the card (as defined | kind "surname2" inside the "name" property of the card (as defined | |||
in Section 2.2.1.2 of [RFC9553]) matches the value. | in Section 2.2.1.2 of [RFC9553]) matches the value. | |||
* *nickname*: String | ||||
*nickname*: String | ||||
A card matches this condition if the "name" of any Nickname in the | A card matches this condition if the "name" of any Nickname in the | |||
"nicknames" property of the card (as defined in Section 2.2.2 of | "nicknames" property of the card (as defined in Section 2.2.2 of | |||
[RFC9553]) matches the value. | [RFC9553]) matches the value. | |||
* *organization*: String | ||||
*organization*: String | ||||
A card matches this condition if the "name" of any Organization in | A card matches this condition if the "name" of any Organization in | |||
the "organizations" property of the card (as defined in | the "organizations" property of the card (as defined in | |||
Section 2.2.3 of [RFC9553]) matches the value. | Section 2.2.3 of [RFC9553]) matches the value. | |||
* *email*: String | ||||
*email*: String | ||||
A card matches this condition if the "address" or "label" of any | A card matches this condition if the "address" or "label" of any | |||
EmailAddress in the "emails" property of the card (as defined in | EmailAddress in the "emails" property of the card (as defined in | |||
Section 2.3.1 of [RFC9553]) matches the value. | Section 2.3.1 of [RFC9553]) matches the value. | |||
* *phone*: String | ||||
*phone*: String | ||||
A card matches this condition if the "number" or "label" of any | A card matches this condition if the "number" or "label" of any | |||
Phone in the "phones" property of the card (as defined in | Phone in the "phones" property of the card (as defined in | |||
Section 2.3.3 of [RFC9553]) matches the value. | Section 2.3.3 of [RFC9553]) matches the value. | |||
* *onlineService*: String | ||||
*onlineService*: String | ||||
A card matches this condition if the "service", "uri", "user", or | A card matches this condition if the "service", "uri", "user", or | |||
"label" of any OnlineService in the "onlineServices" property of | "label" of any OnlineService in the "onlineServices" property of | |||
the card (as defined in Section 2.3.2 of [RFC9553]) matches the | the card (as defined in Section 2.3.2 of [RFC9553]) matches the | |||
value. | value. | |||
* *address*: String | ||||
*address*: String | ||||
A card matches this condition if the value of any AddressComponent | A card matches this condition if the value of any AddressComponent | |||
in the "addresses" property, or the "full" property in the | in the "addresses" property or the "full" property in the | |||
"addresses" property of the card, (as defined in Section 2.5.1 of | "addresses" property of the card (as defined in Section 2.5.1 of | |||
[RFC9553]) matches the value. | [RFC9553]) matches the value. | |||
* *note*: String | ||||
*note*: String | ||||
A card matches this condition if the "note" of any Note in the | A card matches this condition if the "note" of any Note in the | |||
"notes" property of the card (as defined in Section 2.8.3 of | "notes" property of the card (as defined in Section 2.8.3 of | |||
[RFC9553]) matches the value. | [RFC9553]) matches the value. | |||
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: | |||
* Text SHOULD be matched in a case-insensitive manner. | * Text SHOULD be matched in a case-insensitive manner. | |||
* Text contained in either (but matched) single or double quotes | * Text contained in either (but matched) single or double quotes | |||
SHOULD be treated as a *phrase search*, that is a match is | SHOULD be treated as a phrase search. That is, a match is | |||
required for that exact sequence of words, excluding the | required for that exact sequence of words, excluding the | |||
surrounding quotation marks. Use \", \' and \\ to match a literal | surrounding quotation marks. Use \", \', and \\ to match a | |||
", ' and \ respectively in a phrase. | literal ", ', and \ respectively in a phrase. | |||
* Outside of a phrase, white-space SHOULD be treated as dividing | * Outside of a phrase, whitespace SHOULD be treated as dividing | |||
separate tokens that may be searched for separately in the | separate tokens that may be searched for separately in the | |||
contact, but MUST all be present for the contact to match the | contact, but MUST all be present for the contact to match the | |||
filter. | filter. | |||
* Tokens MAY be matched on a whole-word basis using stemming (so for | ||||
example a text search for bus would match "buses" but not | * Tokens MAY be matched on a whole-word basis using stemming (e.g., | |||
"business"). | a text search for bus would match "buses", but not "business"). | |||
3.3.2. Sorting | 3.3.2. Sorting | |||
The following value for the "property" field on the Comparator object | The following values for the "property" field on the Comparator | |||
MUST be supported for sorting: | object MUST be supported for sorting: | |||
* "created" - The "created" date on the ContactCard. | * "created" - The "created" date on the ContactCard. | |||
* "updated" - The "updated" date on the ContactCard. | * "updated" - The "updated" date on the ContactCard. | |||
The following values for the "property" field on the Comparator | The following values for the "property" field on the Comparator | |||
object SHOULD be supported for sorting: | object SHOULD be supported for sorting: | |||
* "name/given" - The value of the first NameComponent in the "name" | * "name/given" - The value of the first NameComponent in the "name" | |||
property whose "kind" is "given". | property whose "kind" is "given". | |||
* "name/surname" - The value of the first NameComponent in the | * "name/surname" - The value of the first NameComponent in the | |||
"name" property whose "kind" is "surname". | "name" property whose "kind" is "surname". | |||
* "name/surname2" - The value of the first NameComponent in the | * "name/surname2" - The value of the first NameComponent in the | |||
"name" property whose "kind" is "surname2". | "name" property whose "kind" is "surname2". | |||
3.4. ContactCard/queryChanges | 3.4. ContactCard/queryChanges | |||
This is a standard "/queryChanges" method as described in [RFC8620], | This is a standard "/queryChanges" method as described in Section 5.6 | |||
Section 5.6. | of [RFC8620]. | |||
3.5. ContactCard/set | 3.5. ContactCard/set | |||
This is a standard "/set" method as described in [RFC8620], | This is a standard "/set" method as described in Section 5.3 of | |||
Section 5.3. | [RFC8620]. | |||
To set a new photo, the file must first be uploaded using the upload | To set a new photo, the file must first be uploaded using the upload | |||
mechanism as described in [RFC8620], Section 6.1. This will give the | mechanism as described in Section 6.1 of [RFC8620]. This will give | |||
client a valid blobId/size/type to use. The server MUST reject | the client a valid blobId, size, and type to use. The server MUST | |||
attempts to set a file that is not a recognised image type as the | reject attempts to set a file that is not a recognised image type as | |||
photo for a card. | the photo for a card. | |||
3.6. ContactCard/copy | 3.6. ContactCard/copy | |||
This is a standard "/copy" method as described in [RFC8620], | This is a standard "/copy" method as described in Section 5.4 of | |||
Section 5.4. | [RFC8620]. | |||
4. Examples | 4. Examples | |||
For brevity, in the following examples only the "methodCalls" | For brevity, only the "methodCalls" property of the Request object | |||
property of the Request object, and the "methodResponses" property of | and the "methodResponses" property of the Response object is shown in | |||
the Response object is shown. | the following examples. | |||
4.1. Fetching initial data | 4.1. Fetching Initial Data | |||
A user has authenticated and the client has fetched the JMAP Session | A user has authenticated and the client has fetched the JMAP Session | |||
object. It finds a single Account with the | object. It finds a single Account with the | |||
"urn:ietf:params:jmap:contacts" capability, with id "a0x9", and wants | "urn:ietf:params:jmap:contacts" capability with id "a0x9" and wants | |||
to fetch all the address books and contacts. It might make the | to fetch all the address books and contacts. It might make the | |||
following request: | following request: | |||
[ | [ | |||
["AddressBook/get", { | ["AddressBook/get", { | |||
"accountId": "a0x9" | "accountId": "a0x9" | |||
}, "0"], | }, "0"], | |||
["ContactCard/get", { | ["ContactCard/get", { | |||
"accountId": "a0x9" | "accountId": "a0x9" | |||
}, "1"] | }, "1"] | |||
] | ] | |||
Figure 1: "methodCalls" Property of a JMAP Request | ||||
The server might respond with something like: | The server might respond with something like: | |||
[ | [ | |||
["AddressBook/get", { | ["AddressBook/get", { | |||
"accountId": "a0x9", | "accountId": "a0x9", | |||
"list": [{ | "list": [{ | |||
"id": "062adcfa-105d-455c-bc60-6db68b69c3f3", | "id": "062adcfa-105d-455c-bc60-6db68b69c3f3", | |||
"name": "Personal", | "name": "Personal", | |||
"description": null, | "description": null, | |||
"sortOrder": 0, | "sortOrder": 0, | |||
"isDefault": true, | "isDefault": true, | |||
"isSubscribed": true, | "isSubscribed": true, | |||
"shareWith": { | "shareWith": { | |||
"3f1502e0-63fe-4335-9ff3-e739c188f5dd": { | "3f1502e0-63fe-4335-9ff3-e739c188f5dd": { | |||
"mayRead": true, | ||||
"mayWrite": false, | ||||
"mayShare": false, | ||||
"mayDelete": false | ||||
} | ||||
}, | ||||
"myRights": { | ||||
"mayRead": true, | ||||
"mayWrite": true, | ||||
"mayShare": true, | ||||
"mayDelete": false | ||||
} | ||||
}, { | ||||
"id": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe", | ||||
"name": "Autosaved", | ||||
"description": null, | ||||
"sortOrder": 1, | ||||
"isDefault": false, | ||||
"isSubscribed": true, | ||||
"shareWith": null, | ||||
"myRights": { | ||||
"mayRead": true, | "mayRead": true, | |||
"mayWrite": true, | "mayWrite": false, | |||
"mayShare": true, | "mayShare": false, | |||
"mayDelete": false | "mayDelete": false | |||
} | } | |||
}], | }, | |||
"notFound": [], | "myRights": { | |||
"state": "~4144" | "mayRead": true, | |||
"mayWrite": true, | ||||
"mayShare": true, | ||||
"mayDelete": false | ||||
} | ||||
}, { | ||||
"id": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe", | ||||
"name": "Autosaved", | ||||
"description": null, | ||||
"sortOrder": 1, | ||||
"isDefault": false, | ||||
"isSubscribed": true, | ||||
"shareWith": null, | ||||
"myRights": { | ||||
"mayRead": true, | ||||
"mayWrite": true, | ||||
"mayShare": true, | ||||
"mayDelete": false | ||||
} | ||||
}], | ||||
"notFound": [], | ||||
"state": "~4144" | ||||
}, "0"], | }, "0"], | |||
["Contact/get", { | ["ContactCard/get", { | |||
"accountId": "a0x9", | "accountId": "a0x9", | |||
"list": [{ | "list": [{ | |||
"id": "3", | "id": "3", | |||
"addressBookIds": { | "addressBookIds": { | |||
"062adcfa-105d-455c-bc60-6db68b69c3f3": true | "062adcfa-105d-455c-bc60-6db68b69c3f3": true | |||
}, | }, | |||
"name": { | "name": { | |||
"components": [ | "components": [ | |||
{ "kind": "given", "value": "Joe" }, | { "kind": "given", "value": "Joe" }, | |||
{ "kind": "surname", "value": "Bloggs" } | { "kind": "surname", "value": "Bloggs" } | |||
], | ], | |||
"isOrdered": true | "isOrdered": true | |||
}, | }, | |||
"emails": { | "emails": { | |||
"0": { | "0": { | |||
"contexts": { | "contexts": { | |||
"private": true | "private": true | |||
}, | }, | |||
"address": "joe.bloggs@example.com" | "address": "joe.bloggs@example.com" | |||
} | ||||
} | } | |||
}], | } | |||
"notFound": [], | }], | |||
"state": "ewarbckaqJ::112" | "notFound": [], | |||
"state": "ewarbckaqJ::112" | ||||
}, "1"] | }, "1"] | |||
] | ] | |||
4.2. Changing the default address book | Figure 2: "methodResponses" Property of a JMAP Response | |||
4.2. Changing the Default Address Book | ||||
The client tries to change the default address book from "Personal" | The client tries to change the default address book from "Personal" | |||
to "Autosaved" (and makes no other change): | to "Autosaved" (and makes no other change): | |||
[ | [ | |||
["AddressBook/set", { | ["AddressBook/set", { | |||
"accountId": "a0x9", | "accountId": "a0x9", | |||
"onSuccessSetIsDefault": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe" | "onSuccessSetIsDefault": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe" | |||
}, "0"] | }, "0"] | |||
] | ] | |||
Figure 3: "methodCalls" Property of a JMAP Request | ||||
The server allows the change, returning the following response: | The server allows the change, returning the following response: | |||
[ | [ | |||
["AddressBook/set", { | ["AddressBook/set", { | |||
"accountId": "a0x9", | "accountId": "a0x9", | |||
"updated": { | "updated": { | |||
"cd40089d-35f9-4fd7-980b-ba3a9f1d74fe": { | "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe": { | |||
"isDefault": true | "isDefault": true | |||
}, | }, | |||
"062adcfa-105d-455c-bc60-6db68b69c3f3": { | "062adcfa-105d-455c-bc60-6db68b69c3f3": { | |||
"isDefault": false | "isDefault": false | |||
} | }, | |||
"oldState": "~4144", | ||||
"newState": "~4148" | ||||
} | } | |||
}, "0"] | }, "0"] | |||
] | ] | |||
Figure 4: "methodResponses" Property of a JMAP Response | ||||
5. Internationalisation Considerations | 5. Internationalisation Considerations | |||
Experience has shown that unrestricted use of Unicode can lead to | Experience has shown that unrestricted use of Unicode can lead to | |||
problems such as inconsistent rendering, users reading text and | problems such as inconsistent rendering, users reading text and | |||
interpreting it differently than intended, and unexpected results | interpreting it differently than intended, and unexpected results | |||
when copying text from one location to another. Servers MAY choose | when copying text from one location to another. Servers MAY choose | |||
to mitigate this by restricting the set of characters allowed in | to mitigate this by restricting the set of characters allowed in | |||
otherwise unconstrained String fields. The FreeformClass, as | otherwise unconstrained String fields. The FreeformClass, as | |||
documented in [RFC8264], Section 4.3 might be a good starting point | documented in Section 4.3 of [RFC8264], might be a good starting | |||
for this. | point for this. | |||
Attempts to set a value containing code points outside of the | Attempts to set a value containing code points outside of the | |||
permissible set can be handled in a few ways by the server. The | permissible set can be handled in a few ways by the server. The | |||
server could choose to strip the forbidden characters, or replace | server could choose to strip the forbidden characters or replace them | |||
them with U+FFFD (the Unicode replacement character), and store the | with U+FFFD (the Unicode replacement character) and store the | |||
resulting string. This is likely to be appropriate for non-printable | resulting string. This is likely to be appropriate for non-printable | |||
characters — such as the "Control Codes" defined in [UNICODE] | characters -- such as the "Control Codes" defined in Section 23.1 | |||
Section 23.1, excluding newline (U+000A), carriage return (U+000D), | (https://www.unicode.org/versions/latest/core-spec/chapter- | |||
and tab (U+0009) — which can end up in data accidentally due to copy- | 23/#G20365) of [UNICODE], excluding newline (U+000A), carriage return | |||
and-paste issues, but are invisible to the end user. JMAP allows the | (U+000D), and tab (U+0009) -- that can end up in data accidentally | |||
server to transform data on create/update, as long as any changed | due to copy-and-paste issues but are invisible to the end user. JMAP | |||
properties are returned to the client in the /set response, so it | allows the server to transform data on create/update as long as any | |||
knows what has changed, as per [RFC8620], Section 5.3. | changed properties are returned to the client in the "/set" response | |||
so it knows what has changed, as per Section 5.3 of [RFC8620]. | ||||
Alternatively, the server MAY just reject the create/update with an | Alternatively, the server MAY just reject the create/update with an | |||
invalidProperties SetError. | "invalidProperties" SetError. | |||
6. Security Considerations | 6. Security Considerations | |||
All security considerations of JMAP ([RFC8620]) apply to this | All security considerations of JMAP [RFC8620] apply to this | |||
specification. Additional considerations specific to the data types | specification. Additional considerations specific to the data types | |||
and functionality introduced by this document are described in the | and functionality introduced by this document are described in the | |||
following subsection. | following subsection. | |||
Contacts consist almost entirely of private, personally identifiable | Contacts consist almost entirely of private, personally identifiable | |||
information, and represent the social connections of users. Privacy | information, and represent the social connections of users. Privacy | |||
leaks can have real world consequences, and contacts servers and | leaks can have real world consequences, and contact servers and | |||
clients MUST be mindful of the need to keep all data secure. | clients MUST be mindful of the need to keep all data secure. | |||
Servers MUST enforce the ACLs set on address books to ensure only | Servers MUST enforce the Access Control Lists (ACLs) set on address | |||
authorised data is shared. | books to ensure only authorised data is shared. | |||
7. IANA Considerations | 7. IANA Considerations | |||
7.1. JMAP capability registration for "contacts" | 7.1. JMAP Capability Registration for "contacts" | |||
IANA will register "contacts" in the "JMAP Capabilities" registry as | IANA has registered "contacts" in the "JMAP Capabilities" registry as | |||
follows: | follows: | |||
Capability Name: urn:ietf:params:jmap:contacts | Capability Name: urn:ietf:params:jmap:contacts | |||
Intended Use: common | ||||
Specification document: this document | Change Controller: IETF | |||
Security and Privacy Considerations: this document, Section 6 | ||||
Intended use: common | Reference: this document | |||
Change Controller: IETF | ||||
Security and privacy considerations: this document, Section 6 | ||||
7.2. JMAP Data Type Registration for "AddressBook" | 7.2. JMAP Data Type Registration for "AddressBook" | |||
IANA will register "AddressBook" in the "JMAP Data Types" registry as | IANA has registered "AddressBook" in the "JMAP Data Types" registry | |||
follows: | as follows: | |||
Type Name: AddressBook | ||||
Can reference blobs: no | ||||
Can Use for State Change: yes | ||||
Capability: urn:ietf:params:jmap:contacts | ||||
Specification document: this document | Type Name: AddressBook | |||
Can Reference Blobs: No | ||||
Can Use for State Change: Yes | ||||
Capability: urn:ietf:params:jmap:contacts | ||||
Reference: this document | ||||
7.3. JMAP Data Type Registration for "ContactCard" | 7.3. JMAP Data Type Registration for "ContactCard" | |||
IANA will register "ContactCard" in the "JMAP Data Types" registry as | IANA has registered "ContactCard" in the "JMAP Data Types" registry | |||
follows: | as follows: | |||
Type Name: ContactCard | ||||
Can reference blobs: yes | ||||
Can Use for State Change: yes | ||||
Capability: urn:ietf:params:jmap:contacts | ||||
Specification document: this document | Type Name: ContactCard | |||
Can Reference Blobs: Yes | ||||
Can Use for State Change: Yes | ||||
Capability: urn:ietf:params:jmap:contacts | ||||
Reference: this document | ||||
7.4. JMAP Error Codes Registry | 7.4. JMAP Error Codes Registry | |||
The following subsection registers a new error code in the "JMAP | The following subsection has registered a new error code in the "JMAP | |||
Error Codes" registry, as defined in Section 9 of [RFC8620]. | Error Codes" registry, as defined in Section 9 of [RFC8620]. | |||
7.4.1. addressBookHasContents | 7.4.1. addressBookHasContents | |||
JMAP Error Code: addressBookHasContents | JMAP Error Code: addressBookHasContents | |||
Intended Use: common | ||||
Intended use: common | Change Controller: IETF | |||
Description: The AddressBook has at least one ContactCard assigned | ||||
Change controller: IETF | to it, and the "onDestroyRemoveContents" argument was false. | |||
Reference: This document, Section 2.3 | ||||
Reference: This document, Section 2.3 | ||||
Description: The AddressBook has at least one ContactCard assigned to | ||||
it, and the "onDestroyRemoveContents" argument was false. | ||||
7.5. JSContact Property Registrations | 7.5. JSContact Property Registrations | |||
IANA will register the following additional properties in the | IANA has registered the following additional properties in the | |||
JSContact Properties Registry, as defined in Section 3 of [RFC9553]. | "JSContact Properties" registry, as defined in Section 3 of | |||
[RFC9553]. | ||||
7.5.1. id | 7.5.1. id | |||
Property Name: id | Property Name: id | |||
Property Type: not applicable | ||||
Property Type: Not applicable | Property Context: Card | |||
Property Context: Card | Intended Usage: reserved | |||
Since Version: 1.0 | ||||
Intended Use: Reserved | Change Controller: IETF | |||
Reference: this document | ||||
Since Version: 1.0 | ||||
Change Controller: IETF | ||||
7.5.2. addressBookIds | 7.5.2. addressBookIds | |||
Property Name: addressBookIds | Property Name: addressBookIds | |||
Property Type: not applicable | ||||
Property Type: Not applicable | Property Context: Card | |||
Intended Usage: reserved | ||||
Property Context: Card | Since Version: 1.0 | |||
Change Controller: IETF | ||||
Intended Use: Reserved | Reference: this document | |||
Since Version: 1.0 | ||||
Change Controller: IETF | ||||
7.5.3. blobId | 7.5.3. blobId | |||
Property Name: blobId | Property Name: blobId | |||
Property Type: not applicable | ||||
Property Type: Not applicable | Property Context: Media | |||
Intended Usage: reserved | ||||
Property Context: Media | Since Version: 1.0 | |||
Change Controller: IETF | ||||
Intended Use: Reserved | Reference: this document | |||
Since Version: 1.0 | ||||
Change Controller: IETF | 8. References | |||
8. Normative References | 8.1. Normative References | |||
[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, | [RFC2397] Masinter, L., "The "data" URL scheme", RFC 2397, | |||
DOI 10.17487/RFC2397, August 1998, | DOI 10.17487/RFC2397, August 1998, | |||
<https://www.rfc-editor.org/info/rfc2397>. | <https://www.rfc-editor.org/info/rfc2397>. | |||
skipping to change at page 18, line 18 ¶ | skipping to change at line 817 ¶ | |||
[RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application | [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application | |||
Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July | Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July | |||
2019, <https://www.rfc-editor.org/info/rfc8620>. | 2019, <https://www.rfc-editor.org/info/rfc8620>. | |||
[RFC9553] Stepanek, R. and M. Loffredo, "JSContact: A JSON | [RFC9553] Stepanek, R. and M. Loffredo, "JSContact: A JSON | |||
Representation of Contact Data", RFC 9553, | Representation of Contact Data", RFC 9553, | |||
DOI 10.17487/RFC9553, May 2024, | DOI 10.17487/RFC9553, May 2024, | |||
<https://www.rfc-editor.org/info/rfc9553>. | <https://www.rfc-editor.org/info/rfc9553>. | |||
[I-D.ietf-jmap-sharing] | [RFC9670] Jenkins, N., Ed., "JSON Meta Application Protocol (JMAP) | |||
Jenkins, N., "JMAP Sharing", Work in Progress, Internet- | Sharing", RFC 9670, DOI 10.17487/RFC9670, November 2024, | |||
Draft, draft-ietf-jmap-sharing-09, 17 April 2024, | <https://www.rfc-editor.org/info/rfc9670>. | |||
<https://datatracker.ietf.org/doc/html/draft-ietf-jmap- | ||||
sharing-09>. | ||||
9. Informative References | 8.2. Informative References | |||
[RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework: | [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework: | |||
Preparation, Enforcement, and Comparison of | Preparation, Enforcement, and Comparison of | |||
Internationalized Strings in Application Protocols", | Internationalized Strings in Application Protocols", | |||
RFC 8264, DOI 10.17487/RFC8264, October 2017, | RFC 8264, DOI 10.17487/RFC8264, October 2017, | |||
<https://www.rfc-editor.org/info/rfc8264>. | <https://www.rfc-editor.org/info/rfc8264>. | |||
[UNICODE] The Unicode Consortium, "The Unicode Standard", | [UNICODE] The Unicode Consortium, "The Unicode Standard", | |||
<http://www.unicode.org/versions/latest/>. Note that this | <https://www.unicode.org/versions/latest/>. | |||
reference is to the latest version of Unicode, rather than | ||||
to a specific release. It is not expected that future | ||||
changes in the Unicode Standard will affect the referenced | ||||
definitions. | ||||
Author's Address | Author's Address | |||
Neil Jenkins (editor) | Neil Jenkins (editor) | |||
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 | |||
End of changes. 136 change blocks. | ||||
405 lines changed or deleted | 399 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. |