rfc9610.original.xml | rfc9610.xml | |||
---|---|---|---|---|
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="UTF-8"?> | |||
<rfc version="3" ipr="trust200902" docName="draft-ietf-jmap-contacts-10" submiss | ||||
ionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XIn | ||||
clude" indexInclude="true" consensus="true"> | ||||
<front> | <!DOCTYPE rfc [ | |||
<title abbrev="JMAP Contacts">JMAP for Contacts</title><seriesInfo value="draft- | <!ENTITY nbsp " "> | |||
ietf-jmap-contacts-10" stream="IETF" status="standard" name="Internet-Draft"></s | <!ENTITY zwsp "​"> | |||
eriesInfo> | <!ENTITY nbhy "‑"> | |||
<author role="editor" initials="N.M." surname="Jenkins" fullname="Neil Jenkins"> | <!ENTITY wj "⁠"> | |||
<organization>Fastmail</organization> | ]> | |||
<address> | ||||
<rfc version="3" ipr="trust200902" docName="draft-ietf-jmap-contacts-10" number= | ||||
"9610" submissionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w | ||||
3.org/2001/XInclude" sortRefs="true" symRefs="true" tocInclude="true" consensus= | ||||
"true" updates="" obsoletes=""> | ||||
<front> | ||||
<title abbrev="JMAP Contacts">JSON Meta Application Protocol (JMAP) for Cont | ||||
acts</title> | ||||
<seriesInfo name="RFC" value="9610"/> | ||||
<author role="editor" initials="N." surname="Jenkins" fullname="Neil Jenkins | ||||
"> | ||||
<organization>Fastmail</organization> | ||||
<address> | ||||
<postal> | <postal> | |||
<street>PO Box 234, Collins St West</street> | <street>PO Box 234, Collins St West</street> | |||
<city>Melbourne</city> | <city>Melbourne</city> | |||
<code>VIC 8007</code> | <code>VIC 8007</code> | |||
<country>Australia</country> | <country>Australia</country> | |||
</postal> | </postal> | |||
<email>neilj@fastmailteam.com</email> | <email>neilj@fastmailteam.com</email> | |||
<uri>https://www.fastmail.com</uri> | <uri>https://www.fastmail.com</uri> | |||
</address> | </address> | |||
</author> | </author> | |||
<date year="2024" month="June" day="07"></date> | <date year="2024" month="December"/> | |||
<area>Applications</area> | <area>ART</area> | |||
<workgroup>JMAP</workgroup> | <workgroup>jmap</workgroup> | |||
<keyword>JMAP</keyword> | <keyword>JMAP</keyword> | |||
<keyword>JSON</keyword> | <keyword>JSON</keyword> | |||
<keyword>contacts</keyword> | <keyword>contacts</keyword> | |||
<abstract> | <abstract> | |||
<t>This document specifies a data model for synchronising contacts data with a s erver using JMAP.</t> | <t>This document specifies a data model for synchronising contact data with a se rver using the JSON Meta Application Protocol (JMAP).</t> | |||
</abstract> | </abstract> | |||
</front> | </front> | |||
<middle> | <middle> | |||
<section anchor="introduction"><name>Introduction</name> | <section anchor="introduction"><name>Introduction</name> | |||
<t>JMAP (<xref target="RFC8620"></xref> JSON Meta Application Protocol) is a gen eric protocol for synchronising data, such as mail, calendars or contacts, betwe en a client and a server. It is optimised for mobile and web environments, and a ims to provide a consistent interface to different data types.</t> | <t>The JSON Meta Application Protocol (JMAP) <xref target="RFC8620"></xref> is a generic protocol for synchronising data, such as mail, calendars, or contacts, between a client and a server. It is optimised for mobile and web environments a nd aims to provide a consistent interface to different data types.</t> | |||
<t>This specification defines a data model for synchronising contacts between a client and a server using JMAP.</t> | <t>This specification defines a data model for synchronising contacts between a client and a server using JMAP.</t> | |||
<section anchor="notational-conventions"><name>Notational Conventions</name> | <section anchor="notational-conventions"><name>Notational Conventions</name> | |||
<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", | <t> | |||
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this d | The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQU | |||
ocument are to be interpreted as described in BCP 14 <xref target="RFC2119"></xr | IRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL | |||
ef> <xref target="RFC8174"></xref> when, and only when, they appear in all capit | NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14> | |||
als, as shown here.</t> | RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", | |||
<t>Type signatures, examples and property descriptions in this document follow t | "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to | |||
he conventions established in <xref target="RFC8620" section="1.1" sectionFormat | be interpreted as | |||
="of" />. The Id, UnsignedInt, and UTCDate data types defined in Sections <xref | described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> | |||
target="RFC8620" section="1.2" sectionFormat="bare" />, <xref target="RFC8620" | when, and only when, they appear in all capitals, as shown here. | |||
section="1.3" sectionFormat="bare" />, and <xref target="RFC8620" section="1.4" | </t> | |||
sectionFormat="bare" /> of <xref target="RFC8620" /> are also used in this docum | ||||
ent.</t> | <t>Type signatures, examples, and property descriptions in this document follow | |||
the conventions established in <xref target="RFC8620" section="1.1" sectionForma | ||||
t="of" />. The Id, UnsignedInt, and UTCDate data types defined in Sections <xre | ||||
f target="RFC8620" section="1.2" sectionFormat="bare" />, <xref target="RFC8620" | ||||
section="1.3" sectionFormat="bare" />, and <xref target="RFC8620" section="1.4" | ||||
sectionFormat="bare" /> of <xref target="RFC8620" /> are also used in this docu | ||||
ment.</t> | ||||
</section> | </section> | |||
<section anchor="terminology"><name>Terminology</name> | <section anchor="terminology"><name>Terminology</name> | |||
<t>The same terminology is used in this document as in the core JMAP specificati on, see <xref target="RFC8620" section="1.6" sectionFormat="comma"></xref>.</t> | <t>The same terminology used in the core JMAP specification (see <xref target="R FC8620" section="1.6" sectionFormat="of"></xref>) is also used in this document. </t> | |||
<t>The terms AddressBook and ContactCard (with these specific capitalizations) a re used to refer to the data types defined in this document and instances of tho se data types.</t> | <t>The terms AddressBook and ContactCard (with these specific capitalizations) a re used to refer to the data types defined in this document and instances of tho se data types.</t> | |||
</section> | </section> | |||
<section anchor="data-model-overview"><name>Data Model Overview</name> | <section anchor="data-model-overview"><name>Data Model Overview</name> | |||
<t>An Account (see <xref target="RFC8620" section="1.6.2" sectionFormat="comma"> | <t>An Account (see <xref target="RFC8620" section="1.6.2" sectionFormat="of"></x | |||
</xref>) with support for the contacts data model contains zero or more AddressB | ref>) with support for the contact data model contains zero or more AddressBook | |||
ook objects, which is a named collection of zero or more ContactCards. A Contact | objects, which is a named collection of zero or more ContactCards. A ContactCard | |||
Card is a representation of a person, company, or other entity, or a group of su | is a representation of a person, company, entity, or a group of such entities i | |||
ch entities, in JSContact Card format, as defined in <xref target="RFC9553" sect | n JSContact Card format, as defined in <xref target="RFC9553" section="2" />. Ea | |||
ion="2" />. Each ContactCard belongs to one or more AddressBooks.</t> | ch ContactCard belongs to one or more AddressBooks.</t> | |||
<t>In servers with support for JMAP Sharing <xref target="I-D.ietf-jmap-sharing" | <t>In servers with support for JMAP Sharing <xref target="RFC9670" />, users may | |||
/>, users may see and configure sharing of contact data with others. Sharing pe | see and configure sharing of contact data with others. Sharing permissions are | |||
rmissions are managed per AddressBook.</t> | managed per AddressBook.</t> | |||
</section> | </section> | |||
<section anchor="addition-to-the-capabilities-object"><name>Addition to the Capa bilities Object</name> | <section anchor="addition-to-the-capabilities-object"><name>Addition to the Capa bilities Object</name> | |||
<t>The capabilities object is returned as part of the JMAP Session object; see < xref target="RFC8620" section="2" sectionFormat="comma"></xref>. This document d efines one additional capability URI.</t> | <t>The capabilities object is returned as part of the JMAP Session object; see < xref target="RFC8620" section="2" sectionFormat="of"></xref>. This document defi nes one additional capability URI.</t> | |||
<section anchor="urn-ietf-params-jmap-contacts"><name>urn:ietf:params:jmap:conta cts</name> | <section anchor="urn-ietf-params-jmap-contacts"><name>urn:ietf:params:jmap:conta cts</name> | |||
<t>This represents support for the AddressBook and ContactCard data types and as | <t>This represents support for the AddressBook and ContactCard data types and as | |||
sociated API methods. The value of this property in the JMAP Session capabilitie | sociated API methods. The value of this property in the JMAP Session "capabiliti | |||
s property is an empty object.</t> | es" property is an empty object.</t> | |||
<t>The value of this property in an account's accountCapabilities property is an | <t>The value of this property in an account's "accountCapabilities" property is | |||
object that MUST contain the following information on server capabilities and p | an object that <bcp14>MUST</bcp14> contain the following information on server c | |||
ermissions for that account:</t> | apabilities and permissions for that account:</t> | |||
<ul spacing="compact"> | <dl spacing="normal" newline="true"> | |||
<li><t><strong>maxAddressBooksPerCard</strong>: <tt>UnsignedInt|null</tt></t> | <dt><strong>maxAddressBooksPerCard</strong>: <tt>UnsignedInt|null</tt></dt> | |||
<t>The maximum number of AddressBooks (see <xref target="addressbooks" />) that | <dd>The maximum number of AddressBooks (see <xref target="addressbooks" />) that | |||
can be assigned to a single ContactCard object (see <xref target="contactcards" | can be assigned to a single ContactCard object (see <xref target="contactcards" | |||
/>). This MUST be an integer >= 1, or null for no limit (or rather, the limit | />). This <bcp14>MUST</bcp14> be an integer >= 1, or null for no limit (or r | |||
is always the number of AddressBooks in the account).</t></li> | ather, the limit is always the number of AddressBooks in the account).</dd> | |||
<li><t><strong>mayCreateAddressBook</strong>: <tt>Boolean</tt></t> | <dt><strong>mayCreateAddressBook</strong>: <tt>Boolean</tt></dt> | |||
<t>The user may create an AddressBook in this account if, and only if, this is t | <dd>The user may create an AddressBook in this account if, and only if, this is | |||
rue.</t></li> | true.</dd> | |||
</ul> | </dl> | |||
</section> | </section> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="addressbooks"><name>AddressBooks</name> | <section anchor="addressbooks"><name>AddressBooks</name> | |||
<t>An AddressBook is a named collection of ContactCards. All ContactCards are as | <t>An AddressBook is a named collection of ContactCards. All ContactCards are as | |||
sociated with one or more AddressBook.</t> | sociated with one or more AddressBooks.</t> | |||
<t>A <strong>AddressBook</strong> object has the following properties:</t> | <t>An <strong>AddressBook</strong> object has the following properties:</t> | |||
<ul> | <dl spacing="normal" newline="true"> | |||
<li><t><strong>id</strong>: <tt>Id</tt> (immutable; server-set)</t> | <dt><strong>id</strong>: <tt>Id</tt> (immutable; server-set)</dt> | |||
<t>The id of the AddressBook.</t></li> | <dd>The id of the AddressBook.</dd> | |||
<li><t><strong>name</strong>: <tt>String</tt></t> | <dt><strong>name</strong>: <tt>String</tt></dt> | |||
<t>The user-visible name of the AddressBook. This MUST NOT be the empty string a | <dd>The user-visible name of the AddressBook. This <bcp14>MUST NOT</bcp14> be th | |||
nd MUST NOT be greater than 255 octets in size when encoded as UTF-8.</t></li> | e empty string and <bcp14>MUST NOT</bcp14> be greater than 255 octets in size wh | |||
<li><t><strong>description</strong>: <tt>String|null</tt> (default: null)</t> | en encoded as UTF-8.</dd> | |||
<t>An optional longer-form description of the AddressBook, to provide context in | <dt><strong>description</strong>: <tt>String|null</tt> (default: null)</dt> | |||
shared environments where users need more than just the name.</t></li> | <dd>An optional long-form description of the AddressBook that provides context i | |||
<li><t><strong>sortOrder</strong>: <tt>UnsignedInt</tt> (default: 0)</t> | n shared environments where users need more than just the name.</dd> | |||
<t>Defines the sort order of AddressBooks when presented in the client's UI, so | <dt><strong>sortOrder</strong>: <tt>UnsignedInt</tt> (default: 0)</dt> | |||
it is consistent between devices. The number MUST be an integer in the range | <dd><t>Defines the sort order of AddressBooks when presented in the client's UI | |||
0 <= sortOrder < 2<sup>31.</sup></t> | so it is consistent between devices. The number <bcp14>MUST</bcp14> be an intege | |||
<t>An AddressBook with a lower order is to be displayed before a AddressBook | r in the range 0 <= sortOrder < 2<sup>31</sup>.</t> | |||
with a higher order in any list of AddressBooks in the client's UI. AddressBooks | <t>An AddressBook with a lower order is to be displayed before a AddressBook wit | |||
with equal order should be sorted in alphabetical order by name. The sorting s | h a higher order in any list of AddressBooks in the client's UI. AddressBooks wi | |||
hould take into account locale-specific character order convention.</t> | th equal order should be sorted in alphabetical order by name. The sorting shou | |||
</li> | ld take into account locale-specific character order convention.</t></dd> | |||
<li><t><strong>isDefault</strong>: <tt>Boolean</tt> (server-set)</t> | <dt><strong>isDefault</strong>: <tt>Boolean</tt> (server-set)</dt> | |||
<t>This SHOULD be true for exactly one AddressBook in any account, and MUST NOT | <dd>This <bcp14>SHOULD</bcp14> be true for exactly one AddressBook in any accoun | |||
t and <bcp14>MUST NOT</bcp14> | ||||
be true for more than one AddressBook within an account. The default | be true for more than one AddressBook within an account. The default | |||
AddressBook should be used by clients whenever they need to choose an | AddressBook should be used by clients whenever they need to choose an | |||
AddressBook for the user within this account, and they do not have any other | AddressBook for the user within this account and they do not have any other | |||
information on which to make a choice. For example, if the user creates a new | information on which to make a choice. For example, if the user creates a new | |||
contact card, the client may automatically set the card as belonging to the | contact card, the client may automatically set the card as belonging to the | |||
default AddressBook from the user's primary account.</t> | default AddressBook from the user's primary account.</dd> | |||
</li> | <dt><strong>isSubscribed</strong>: <tt>Boolean</tt></dt> | |||
<li><t><strong>isSubscribed</strong>: <tt>Boolean</tt></t> | <dd><t>True if the user has indicated they wish to see this AddressBook in their | |||
<t>True if the user has indicated they wish to see this AddressBook in their cli | client. This <bcp14>SHOULD</bcp14> default to false for AddressBooks in shared | |||
ent. This SHOULD default to false for AddressBooks in shared accounts the user h | accounts that the user has access to and true for any new AddressBooks created b | |||
as access to and true for any new AddressBooks created by the user themself.</t> | y the user themself.</t> | |||
<t>If false, the AddressBook and its contents SHOULD only be displayed when | <t>If false, the AddressBook and its contents <bcp14>SHOULD</bcp14> only be | |||
the user explicitly requests it or to offer it for the user to subscribe to.</t> | displayed when the user explicitly requests it. The UI may offer to the user the | |||
</li> | option of subscribing to it.</t> | |||
<li><t><strong>shareWith</strong>: <tt>Id[AddressBookRights]|null</tt> (default: | </dd> | |||
null)</t> | <dt><strong>shareWith</strong>: <tt>Id[AddressBookRights]|null</tt> (default: nu | |||
<t>A map of Principal (<xref target="I-D.ietf-jmap-sharing" section="2" />) id t | ll)</dt> | |||
o rights for principals this AddressBook is shared with. The principal to which | <dd>A map of the Principal id (<xref target="RFC9670" section="2" />) to rights | |||
this AddressBook belongs MUST NOT be in this set. This is null if the AddressBoo | for Principals this AddressBook is shared with. The Principal to which this Addr | |||
k is not shared with anyone, or the server does not support <xref target="I-D.ie | essBook belongs <bcp14>MUST NOT</bcp14> be in this set. This is null if the Addr | |||
tf-jmap-sharing" />. The value may be modified only if the user has the mayShare | essBook is not shared with anyone or if the server does not support <xref target | |||
right. The account id for the principals may be found in the <tt>urn:ietf:param | ="RFC9670" />. The value may be modified only if the user has the "mayShare" rig | |||
s:jmap:principals:owner</tt> capability of the Account to which the AddressBook | ht. The account id for the Principals may be found in the <tt>urn:ietf:params:jm | |||
belongs.</t> | ap:principals:owner</tt> capability of the Account to which the AddressBook belo | |||
</li> | ngs.</dd> | |||
<li><t><strong>myRights</strong>: <tt>AddressBookRights</tt> (server-set)</t> | <dt><strong>myRights</strong>: <tt>AddressBookRights</tt> (server-set)</dt> | |||
<t>The set of access rights the user has in relation to this AddressBook.</t> | <dd>The set of access rights the user has in relation to this AddressBook.</dd> | |||
</li> | </dl> | |||
</ul> | ||||
<t>An <strong>AddressBookRights</strong> object has the following properties:</t > | <t>An <strong>AddressBookRights</strong> object has the following properties:</t > | |||
<ul spacing="compact"> | <dl spacing="normal" newline="true"> | |||
<li><t><strong>mayRead</strong>: <tt>Boolean</tt></t> | <dt><strong>mayRead</strong>: <tt>Boolean</tt></dt> | |||
<t>The user may fetch the ContactCards in this AddressBook.</t></li> | <dd>The user may fetch the ContactCards in this AddressBook.</dd> | |||
<li><t><strong>mayWrite</strong>: <tt>Boolean</tt></t> | <dt><strong>mayWrite</strong>: <tt>Boolean</tt></dt> | |||
<t>The user may create, modify or destroy all ContactCards in this AddressBook, | <dd>The user may create, modify, or destroy all ContactCards in this AddressBook | |||
or move them to or from this AddressBook.</t></li> | , or move them to or from this AddressBook.</dd> | |||
<li><t><strong>mayShare</strong>: <tt>Boolean</tt></t> | <dt><strong>mayShare</strong>: <tt>Boolean</tt></dt> | |||
<t>The user may modify the "shareWith" property for this AddressBook.</t></li> | <dd>The user may modify the "shareWith" property for this AddressBook.</dd> | |||
<li><t><strong>mayDelete</strong>: <tt>Boolean</tt></t> | <dt><strong>mayDelete</strong>: <tt>Boolean</tt></dt> | |||
<t>The user may delete the AddressBook itself.</t></li> | <dd>The user may delete the AddressBook itself.</dd> | |||
</ul> | </dl> | |||
<section anchor="addressbook-get"><name>AddressBook/get</name> | <section anchor="addressbook-get"><name>AddressBook/get</name> | |||
<t>This is a standard "/get" method as described in <xref target="RFC8620" secti on="5.1" sectionFormat="comma"></xref>. The <em>ids</em> argument may be <tt>nul l</tt> to fetch all at once.</t> | <t>This is a standard "/get" method as described in <xref target="RFC8620" secti on="5.1" sectionFormat="of"></xref>. The "ids" argument may be null to fetch all at once.</t> | |||
</section> | </section> | |||
<section anchor="addressbook-changes"><name>AddressBook/changes</name> | <section anchor="addressbook-changes"><name>AddressBook/changes</name> | |||
<t>This is a standard "/changes" method as described in <xref target="RFC8620" s ection="5.2" sectionFormat="comma"></xref>.</t> | <t>This is a standard "/changes" method as described in <xref target="RFC8620" s ection="5.2" sectionFormat="of"></xref>.</t> | |||
</section> | </section> | |||
<section anchor="addressbook-set"><name>AddressBook/set</name> | <section anchor="addressbook-set"><name>AddressBook/set</name> | |||
<t>This is a standard "/set" method as described in <xref target="RFC8620" secti on="5.3" sectionFormat="comma"></xref> but with the following additional request argument:</t> | <t>This is a standard "/set" method as described in <xref target="RFC8620" secti on="5.3" sectionFormat="of"></xref>, but with the following additional request a rguments:</t> | |||
<ul> | <dl spacing="normal" newline="true"> | |||
<li><t><strong>onDestroyRemoveContents</strong>: <tt>Boolean</tt> (default: fals | <dt><strong>onDestroyRemoveContents</strong>: <tt>Boolean</tt> (default: false)< | |||
e)</t> | /dt> | |||
<t>If false, any attempt to destroy an AddressBook that still has a ContactCard | <dd>If false, any attempt to destroy an AddressBook that still has a ContactCard | |||
in it will be rejected with an <tt>addressBookHasContents</tt> SetError. If | in it will be rejected with an "addressBookHasContents" SetError. If | |||
true, any ContactCard that is in the AddressBook will be removed from it, and if | true, any ContactCard that is in the AddressBook will be removed from it, and if | |||
such a ContactCard does not belong to any other AddressBook it will be destroye | such a ContactCard does not belong to any other AddressBook, it will be destroy | |||
d.</t> | ed.</dd> | |||
</li> | <dt><strong>onSuccessSetIsDefault</strong>: <tt>Id|null</tt></dt> | |||
<li><t><strong>onSuccessSetIsDefault</strong>: <tt>Id|null</tt></t> | <dd>If an id is given, and all creates, updates, and destroys (if any) succeed | |||
<t>If an id is given, and all creates, updates and destroys (if any) succeed | ||||
without error, the server will try to set this AddressBook as the default. | without error, the server will try to set this AddressBook as the default. | |||
(For references to AddressBook creations, this is equivalent to a | (For references to AddressBook creations, this is equivalent to a | |||
creation-reference, so the id will be the creation id prefixed with a "#".)</t> | creation-reference, so the id will be the creation id prefixed with a "#".)</dd> | |||
</li> | </dl> | |||
</ul> | ||||
<t>If the id is not found, or the change is not permitted by the server for | ||||
policy reasons, it MUST be ignored and the currently default AddressBook (if | ||||
any) will remain as such. No error is returned to the client in this case.</t> | ||||
<t>As per <xref target="RFC8620" section="5.3" sectionFormat="comma"></xref>, if | ||||
the default is successfully changed, any | ||||
changed objects MUST be reported in either the "created" or "updated" | ||||
argument in the response as appropriate, with the server-set value included.< | ||||
/t> | ||||
<t>The "shareWith" property may only be set by users that have the mayShare righ | ||||
t. When modifying the shareWith property, the user cannot give a right to a prin | ||||
cipal if the principal did not already have that right and the user making the c | ||||
hange also does not have that right. Any attempt to do so MUST be rejected with | ||||
a <tt>forbidden</tt> SetError.</t> | ||||
<t>Users can subscribe or unsubscribe to an AddressBook by setting the "isSubscr | ||||
ibed" property. The server MAY forbid users from subscribing to certain AddressB | ||||
ooks even though they have permission to see them, rejecting the update with a < | ||||
tt>forbidden</tt> SetError.</t> | ||||
<t>The following extra SetError type is defined:</t> | ||||
<t>For "destroy":</t> | ||||
<ul spacing="compact"> | <t>If the id is not found or if the change is not permitted by the server for | |||
<li><strong>addressBookHasContents</strong>: The AddressBook has at least one Co | policy reasons, it <bcp14>MUST</bcp14> be ignored and the current default | |||
ntactCard assigned to it, and the "onDestroyRemoveContents" argument was false.< | AddressBook (if any) will remain as such. No error is returned to the client | |||
/li> | in this case.</t> | |||
</ul> | <t>As per <xref target="RFC8620" section="5.3" sectionFormat="of"></xref>, if th | |||
e default AddressBook is successfully changed, any changed objects <bcp14>MUST</ | ||||
bcp14> be reported in either the "created" or "updated" argument in the response | ||||
as appropriate, with the server-set value included.</t> | ||||
<t>The "shareWith" property may only be set by users that have the "mayShare" ri | ||||
ght. When modifying the "shareWith" property, the user cannot give a right to a | ||||
Principal if the Principal did not already have that right and the user making t | ||||
he change also does not have that right. Any attempt to do so <bcp14>MUST</bcp14 | ||||
> be rejected with a "forbidden" SetError.</t> | ||||
<t>Users can subscribe or unsubscribe to an AddressBook by setting the "isSubscr | ||||
ibed" property. The server <bcp14>MAY</bcp14> forbid users from subscribing to c | ||||
ertain AddressBooks even though they have permission to see them, rejecting the | ||||
update with a "forbidden" SetError.</t> | ||||
<t>The following extra SetError type is defined for "destroy":</t> | ||||
<dl spacing="normal"> | ||||
<dt><strong>addressBookHasContents</strong>:</dt> <dd>The AddressBook has at lea | ||||
st one ContactCard assigned to it and the "onDestroyRemoveContents" argument was | ||||
false.</dd> | ||||
</dl> | ||||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="contactcards"><name>ContactCards</name> | <section anchor="contactcards"><name>ContactCards</name> | |||
<t>A <strong>ContactCard</strong> object contains information about a person, co mpany, or other entity, or represents a group of such entities. It is a JSContac t Card object, as defined in <xref target="RFC9553" section="2" />, with the fol lowing additional properties:</t> | <t>A <strong>ContactCard</strong> object contains information about a person, co mpany, or other entity, or represents a group of such entities. It is a JSContac t Card object as defined in <xref target="RFC9553" section="2" /> with the follo wing additional properties:</t> | |||
<ul spacing="compact"> | <dl spacing="normal" newline="true"> | |||
<li><t><strong>id</strong>: <tt>Id</tt> (immutable; server-set)</t> | <dt><strong>id</strong>: <tt>Id</tt> (immutable; server-set)</dt> | |||
<t>The id of the ContactCard. The id property MAY be different to the ContactCar | <dd>The id of the ContactCard. The "id" property <bcp14>MAY</bcp14> be different | |||
d's "uid" property (as defined in <xref target="RFC9553" section="2.1.9" />). Ho | to the ContactCard's "uid" property (as defined in <xref target="RFC9553" secti | |||
wever there MUST NOT be more than one ContactCard with the same "uid" in an Acco | on="2.1.9" />). However, there <bcp14>MUST NOT</bcp14> be more than one ContactC | |||
unt.</t></li> | ard with the same uid in an Account.</dd> | |||
<li><t><strong>addressBookIds</strong>: <tt>Id[Boolean]</tt></t> | <dt><strong>addressBookIds</strong>: <tt>Id[Boolean]</tt></dt> | |||
<t>The set of AddressBook ids this ContactCard belongs to. A card MUST belong to | <dd>The set of AddressBook ids that this ContactCard belongs to. A card <bcp14>M | |||
at least one AddressBook at all times (until it is destroyed). The set is repre | UST</bcp14> belong to at least one AddressBook at all times (until it is destroy | |||
sented as an object, with each key being an AddressBook id. The value for each k | ed). The set is represented as an object, with each key being an AddressBook id. | |||
ey in the object MUST be true.</t></li> | The value for each key in the object <bcp14>MUST</bcp14> be true.</dd> | |||
</ul> | </dl> | |||
<t>For any Media object in the card (see <xref target="RFC9553" section="2.6.4" />), a new property is defined:</t> | <t>For any Media object in the card (see <xref target="RFC9553" section="2.6.4" />), a new property is defined:</t> | |||
<ul spacing="compact"> | <dl spacing="normal" newline="true"> | |||
<li><t><strong>blobId</strong>: <tt>Id</tt></t> | <dt><strong>blobId</strong>: <tt>Id</tt></dt> | |||
<t>An id for the Blob representing the binary contents of the resource.</t></li> | <dd>An id for the Blob representing the binary contents of the resource.</dd> | |||
</ul> | </dl> | |||
<t>When returning ContactCards, any Media with a URI that uses the <tt>data</tt> | <t>When returning ContactCards, any Media with a URI that uses the "data:" URL s | |||
URL scheme (<xref target="RFC2397" />) SHOULD return a <tt>blobId</tt> property | cheme <xref target="RFC2397" /> <bcp14>SHOULD</bcp14> return a "blobId" property | |||
and omit the <tt>uri</tt> property, as this lets clients load the (potentially | and omit the "uri" property, as this lets clients load the (potentially large) | |||
large) image file only when needed, and avoids the overhead of Base64 encoding. | image file only when needed and avoids the overhead of Base64 encoding. The "med | |||
The "mediaType" property MUST also be set. Similarly, when creating or updating | iaType" property <bcp14>MUST</bcp14> also be set. Similarly, when creating or up | |||
a ContactCard, clients MAY send a <tt>blobId</tt> instead of the <tt>uri</tt> pr | dating a ContactCard, clients <bcp14>MAY</bcp14> send a "blobId" instead of the | |||
operty for a Media object.</t> | "uri" property for a Media object.</t> | |||
<t>A contact card with a "kind" property equal to "group" represents a group of | <t>A contact card with a "kind" property equal to "group" represents a group of | |||
contacts. Clients often present these separately from other contact cards. The " | contacts. Clients often present these separately from other contact cards. The " | |||
members" property, as defined in <xref target="RFC9553" section="2.1.6" />, cont | members" property, as defined in <xref target="RFC9553" section="2.1.6" />, cont | |||
ains a set of UIDs (as defined in <xref target="RFC9553" section="2.1.9" />) for | ains a set of uids (as defined in <xref target="RFC9553" section="2.1.9" />) for | |||
other contacts that are the members of this group. Clients should consider the | other contacts that are the members of this group. | |||
group to contain any ContactCard with a matching UID, from any account they have | Clients should consider the group to contain any ContactCard with a matching uid | |||
access to with support for the <tt>urn:ietf:params:jmap:contacts</tt> capabilit | from any account they have access to that has support for the <tt>urn:ietf:para | |||
y. UIDs that cannot be found SHOULD be ignored but preserved. For example, suppo | ms:jmap:contacts</tt> capability. Any uid that cannot be found <bcp14>SHOULD</bc | |||
se a user adds contacts from a shared address book to their private group, then | p14> be ignored but preserved. For example, suppose a user adds contacts from a | |||
temporarily loses access to this address book. The UIDs cannot be resolved so th | shared address book to their private group, then temporarily loses access to thi | |||
e contacts will disappear from the group. However, if they are given permission | s address book. The uids cannot be resolved, so the contacts will disappear from | |||
to access the data again the UIDs will be found and the contacts will reappear.< | the group. However, if they are given permission to access the data again, the | |||
/t> | uids will be found and the contacts will reappear.</t> | |||
<section anchor="contactcard-get"><name>ContactCard/get</name> | <section anchor="contactcard-get"><name>ContactCard/get</name> | |||
<t>This is a standard "/get" method as described in <xref target="RFC8620" secti on="5.1" sectionFormat="comma"></xref>.</t> | <t>This is a standard "/get" method as described in <xref target="RFC8620" secti on="5.1" sectionFormat="of"></xref>.</t> | |||
</section> | </section> | |||
<section anchor="contactcard-changes"><name>ContactCard/changes</name> | <section anchor="contactcard-changes"><name>ContactCard/changes</name> | |||
<t>This is a standard "/changes" method as described in <xref target="RFC8620" s ection="5.2" sectionFormat="comma"></xref>.</t> | <t>This is a standard "/changes" method as described in <xref target="RFC8620" s ection="5.2" sectionFormat="of"></xref>.</t> | |||
</section> | </section> | |||
<section anchor="contactcard-query"><name>ContactCard/query</name> | <section anchor="contactcard-query"><name>ContactCard/query</name> | |||
<t>This is a standard "/query" method as described in <xref target="RFC8620" sec tion="5.5" sectionFormat="comma"></xref>.</t> | <t>This is a standard "/query" method as described in <xref target="RFC8620" sec tion="5.5" sectionFormat="of"></xref>.</t> | |||
<section anchor="filtering"><name>Filtering</name> | <section anchor="filtering"><name>Filtering</name> | |||
<t>A <strong>FilterCondition</strong> object has the following properties, any o f which may be omitted:</t> | <t>A <strong>FilterCondition</strong> object has the following properties, any o f which may be omitted:</t> | |||
<ul spacing="compact"> | <dl spacing="normal" newline="true"> | |||
<li><t><strong>inAddressBook</strong>: <tt>Id</tt></t> | <dt><strong>inAddressBook</strong>: <tt>Id</tt></dt> | |||
<t>An AddressBook id. A card must be in this address book to match the condition | <dd>An AddressBook id. A card must be in this address book to match the conditio | |||
.</t></li> | n.</dd> | |||
<li><t><strong>uid</strong>: <tt>String</tt></t> | <dt><strong>uid</strong>: <tt>String</tt></dt> | |||
<t>A card must have this string exactly as its uid (as defined in <xref target=" | <dd>A card must have this string exactly as its uid (as defined in <xref target= | |||
RFC9553" section="2.1.9" />) to match.</t></li> | "RFC9553" section="2.1.9" />) to match.</dd> | |||
<li><t><strong>hasMember</strong>: <tt>String</tt></t> | <dt><strong>hasMember</strong>: <tt>String</tt></dt> | |||
<t>A card must have a "members" property (as defined in <xref target="RFC9553" s | <dd>A card must have a "members" property (as defined in <xref target="RFC9553" | |||
ection="2.1.6" />) that contains this string as one of the uids in the set to ma | section="2.1.6" />) that contains this string as one of the uids in the set to m | |||
tch.</t></li> | atch.</dd> | |||
<li><t><strong>kind</strong>: <tt>String</tt></t> | <dt><strong>kind</strong>: <tt>String</tt></dt> | |||
<t>A card must have a kind property (as defined in <xref target="RFC9553" sectio | <dd>A card must have a "kind" property (as defined in <xref target="RFC9553" sec | |||
n="2.1.4" />) that equals this string exactly to match.</t></li> | tion="2.1.4" />) that equals this string exactly to match.</dd> | |||
<li><t><strong>createdBefore</strong>: <tt>UTCDate</tt></t> | <dt><strong>createdBefore</strong>: <tt>UTCDate</tt></dt> | |||
<t>The "created" date-time of the ContactCard (as defined in <xref target="RFC95 | <dd>The "created" date-time of the ContactCard (as defined in <xref target="RFC9 | |||
53" section="2.1.3" />) must be before this date-time to match the condition.</t | 553" section="2.1.3" />) must be before this date-time to match the condition.</ | |||
></li> | dd> | |||
<li><t><strong>createdAfter</strong>: <tt>UTCDate</tt></t> | <dt><strong>createdAfter</strong>: <tt>UTCDate</tt></dt> | |||
<t>The "created" date-time of the ContactCard (as defined in <xref target="RFC95 | <dd>The "created" date-time of the ContactCard (as defined in <xref target="RFC9 | |||
53" section="2.1.3" />) must be the same or after this date-time to match the co | 553" section="2.1.3" />) must be the same or after this date-time to match the c | |||
ndition.</t></li> | ondition.</dd> | |||
<li><t><strong>updatedBefore</strong>: <tt>UTCDate</tt></t> | <dt><strong>updatedBefore</strong>: <tt>UTCDate</tt></dt> | |||
<t>The "updated" date-time of the ContactCard (as defined in <xref target="RFC95 | <dd>The "updated" date-time of the ContactCard (as defined in <xref target="RFC9 | |||
53" section="2.1.10" />) must be before this date-time to match the condition.</ | 553" section="2.1.10" />) must be before this date-time to match the condition.< | |||
t></li> | /dd> | |||
<li><t><strong>updatedAfter</strong>: <tt>UTCDate</tt></t> | <dt><strong>updatedAfter</strong>: <tt>UTCDate</tt></dt> | |||
<t>The "updated" date-time of the ContactCard (as defined in <xref target="RFC95 | <dd>The "updated" date-time of the ContactCard (as defined in <xref target="RFC9 | |||
53" section="2.1.10" />) must be the same or after this date-time to match the c | 553" section="2.1.10" />) must be the same or after this date-time to match the | |||
ondition.</t></li> | condition.</dd> | |||
<li><t><strong>text</strong>: <tt>String</tt></t> | <dt><strong>text</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the text matches with text in the card.</t>< | <dd>A card matches this condition if the text matches with text in the card.</dd | |||
/li> | > | |||
<li><t><strong>name</strong>: <tt>String</tt></t> | <dt><strong>name</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the value of any NameComponent in the "name" | <dd>A card matches this condition if the value of any NameComponent in the "name | |||
property, or the "full" property in the "name" property of the card, (as define | " property or the "full" property in the "name" property of the card (as defined | |||
d in <xref target="RFC9553" section="2.2.1.2" />) matches the value.</t></li> | in <xref target="RFC9553" section="2.2.1.2" />) matches the value.</dd> | |||
<li><t><strong>name/given</strong>: <tt>String</tt></t> | <dt><strong>name/given</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the value of a NameComponent with kind "give | <dd>A card matches this condition if the value of a NameComponent with kind "giv | |||
n" inside the "name" property of the card (as defined in <xref target="RFC9553" | en" inside the "name" property of the card (as defined in <xref target="RFC9553" | |||
section="2.2.1.2" />) matches the value.</t></li> | section="2.2.1.2" />) matches the value.</dd> | |||
<li><t><strong>name/surname</strong>: <tt>String</tt></t> | <dt><strong>name/surname</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the value of a NameComponent with kind "surn | <dd>A card matches this condition if the value of a NameComponent with kind "sur | |||
ame" inside the "name" property of the card (as defined in <xref target="RFC9553 | name" inside the "name" property of the card (as defined in <xref target="RFC955 | |||
" section="2.2.1.2" />) matches the value.</t></li> | 3" section="2.2.1.2" />) matches the value.</dd> | |||
<li><t><strong>name/surname2</strong>: <tt>String</tt></t> | <dt><strong>name/surname2</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the value of a NameComponent with kind "surn | <dd>A card matches this condition if the value of a NameComponent with kind "sur | |||
ame2" inside the "name" property of the card (as defined in <xref target="RFC955 | name2" inside the "name" property of the card (as defined in <xref target="RFC95 | |||
3" section="2.2.1.2" />) matches the value.</t></li> | 53" section="2.2.1.2" />) matches the value.</dd> | |||
<li><t><strong>nickname</strong>: <tt>String</tt></t> | <dt><strong>nickname</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the "name" of any Nickname in the "nicknames | <dd>A card matches this condition if the "name" of any Nickname in the "nickname | |||
" property of the card (as defined in <xref target="RFC9553" section="2.2.2" />) | s" property of the card (as defined in <xref target="RFC9553" section="2.2.2" /> | |||
matches the value.</t></li> | ) matches the value.</dd> | |||
<li><t><strong>organization</strong>: <tt>String</tt></t> | <dt><strong>organization</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the "name" of any Organization in the "organ | <dd>A card matches this condition if the "name" of any Organization in the "orga | |||
izations" property of the card (as defined in <xref target="RFC9553" section="2. | nizations" property of the card (as defined in <xref target="RFC9553" section="2 | |||
2.3" />) matches the value.</t></li> | .2.3" />) matches the value.</dd> | |||
<li><t><strong>email</strong>: <tt>String</tt></t> | <dt><strong>email</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the "address" or "label" of any EmailAddress | <dd>A card matches this condition if the "address" or "label" of any EmailAddres | |||
in the "emails" property of the card (as defined in <xref target="RFC9553" sect | s in the "emails" property of the card (as defined in <xref target="RFC9553" sec | |||
ion="2.3.1" />) matches the value.</t></li> | tion="2.3.1" />) matches the value.</dd> | |||
<li><t><strong>phone</strong>: <tt>String</tt></t> | <dt><strong>phone</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the "number" or "label" of any Phone in the | <dd>A card matches this condition if the "number" or "label" of any Phone in the | |||
"phones" property of the card (as defined in <xref target="RFC9553" section="2.3 | "phones" property of the card (as defined in <xref target="RFC9553" section="2. | |||
.3" />) matches the value.</t></li> | 3.3" />) matches the value.</dd> | |||
<li><t><strong>onlineService</strong>: <tt>String</tt></t> | <dt><strong>onlineService</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the "service", "uri", "user", or "label" of | <dd>A card matches this condition if the "service", "uri", "user", or "label" of | |||
any OnlineService in the "onlineServices" property of the card (as defined in <x | any OnlineService in the "onlineServices" property of the card (as defined in < | |||
ref target="RFC9553" section="2.3.2" />) matches the value.</t></li> | xref target="RFC9553" section="2.3.2" />) matches the value.</dd> | |||
<li><t><strong>address</strong>: <tt>String</tt></t> | <dt><strong>address</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the value of any AddressComponent in the "ad | <dd>A card matches this condition if the value of any AddressComponent in the "a | |||
dresses" property, or the "full" property in the "addresses" property of the car | ddresses" property or the "full" property in the "addresses" property of the car | |||
d, (as defined in <xref target="RFC9553" section="2.5.1" />) matches the value.< | d (as defined in <xref target="RFC9553" section="2.5.1" />) matches the value.</ | |||
/t></li> | dd> | |||
<li><t><strong>note</strong>: <tt>String</tt></t> | <dt><strong>note</strong>: <tt>String</tt></dt> | |||
<t>A card matches this condition if the "note" of any Note in the "notes" proper | <dd>A card matches this condition if the "note" of any Note in the "notes" prope | |||
ty of the card (as defined in <xref target="RFC9553" section="2.8.3" />) matches | rty of the card (as defined in <xref target="RFC9553" section="2.8.3" />) matche | |||
the value.</t></li> | s the value.</dd> | |||
</ul> | </dl> | |||
<t>If zero properties are specified on the FilterCondition, the condition MUST a | <t>If zero properties are specified on the FilterCondition, the condition <bcp14 | |||
lways evaluate to <tt>true</tt>. If multiple properties are specified, ALL must | >MUST</bcp14> always evaluate to true. If multiple properties are specified, ALL | |||
apply for the condition to be <tt>true</tt> (it is equivalent to splitting the o | must apply for the condition to be true (it is equivalent to splitting the obje | |||
bject into one-property conditions and making them all the child of an AND filte | ct into one-property conditions and making them all the child of an AND filter o | |||
r operator).</t> | perator).</t> | |||
<t>The exact semantics for matching <tt>String</tt> fields is <strong>deliberate | <t>The exact semantics for matching <tt>String</tt> fields is deliberately not d | |||
ly not defined</strong> to allow for flexibility in indexing implementation, sub | efined to allow for flexibility in indexing implementation, subject to the follo | |||
ject to the following:</t> | wing:</t> | |||
<ul spacing="compact"> | <ul spacing="normal"> | |||
<li>Text SHOULD be matched in a case-insensitive manner.</li> | <li>Text <bcp14>SHOULD</bcp14> be matched in a case-insensitive manner.</li> | |||
<li>Text contained in either (but matched) single or double quotes SHOULD be tre | <li>Text contained in either (but matched) single or double quotes <bcp14>SHOULD | |||
ated as a <strong>phrase search</strong>, that is a match is required for that e | </bcp14> be treated as a phrase search. That is, a match is required for that ex | |||
xact sequence of words, excluding the surrounding quotation marks. Use <tt>\"</t | act sequence of words, excluding the surrounding quotation marks. Use <tt>\"</tt | |||
t>, <tt>\'</tt> and <tt>\\</tt> to match a literal <tt>"</tt>, <tt>'</tt> and <t | >, <tt>\'</tt>, and <tt>\\</tt> to match a literal <tt>"</tt>, <tt>'</tt>, and < | |||
t>\</tt> respectively in a phrase.</li> | tt>\</tt> respectively in a phrase.</li> | |||
<li>Outside of a phrase, white-space SHOULD be treated as dividing separate toke | <li>Outside of a phrase, whitespace <bcp14>SHOULD</bcp14> be treated as dividing | |||
ns that may be searched for separately in the contact, but MUST all be present f | separate tokens that may be searched for separately in the contact, but <bcp14> | |||
or the contact to match the filter.</li> | MUST</bcp14> all be present for the contact to match the filter.</li> | |||
<li>Tokens MAY be matched on a whole-word basis using stemming (so for example a | <li>Tokens <bcp14>MAY</bcp14> be matched on a whole-word basis using stemming (e | |||
text search for <tt>bus</tt> would match "buses" but not "business").</li> | .g., a text search for <tt>bus</tt> would match "buses", but not "business").</l | |||
i> | ||||
</ul> | </ul> | |||
</section> | </section> | |||
<section anchor="sorting"><name>Sorting</name> | <section anchor="sorting"><name>Sorting</name> | |||
<t>The following value for the "property" field on the Comparator object | <t>The following values for the "property" field on the Comparator object | |||
MUST be supported for sorting:</t> | <bcp14>MUST</bcp14> be supported for sorting:</t> | |||
<ul spacing="compact"> | <ul spacing="normal"> | |||
<li>"created" - The "created" date on the ContactCard.</li> | <li>"created" - The "created" date on the ContactCard.</li> | |||
<li>"updated" - The "updated" date on the ContactCard.</li> | <li>"updated" - The "updated" date on the ContactCard.</li> | |||
</ul> | </ul> | |||
<t>The following values for the "property" field on the Comparator object SHOULD be supported for sorting:</t> | <t>The following values for the "property" field on the Comparator object <bcp14 >SHOULD</bcp14> be supported for sorting:</t> | |||
<ul spacing="compact"> | <ul spacing="normal"> | |||
<li>"name/given" - The value of the first NameComponent in the "name" property | <li>"name/given" - The value of the first NameComponent in the "name" property | |||
whose "kind" is "given".</li> | whose "kind" is "given".</li> | |||
<li>"name/surname" - The value of the first NameComponent in the "name" property | <li>"name/surname" - The value of the first NameComponent in the "name" property | |||
whose "kind" is "surname".</li> | whose "kind" is "surname".</li> | |||
<li>"name/surname2" - The value of the first NameComponent in the "name" | <li>"name/surname2" - The value of the first NameComponent in the "name" | |||
property whose "kind" is "surname2".</li> | property whose "kind" is "surname2".</li> | |||
</ul> | </ul> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="contactcard-querychanges"><name>ContactCard/queryChanges</name> | <section anchor="contactcard-querychanges"><name>ContactCard/queryChanges</name> | |||
<t>This is a standard "/queryChanges" method as described in <xref target="RFC86 20" section="5.6" sectionFormat="comma"></xref>.</t> | <t>This is a standard "/queryChanges" method as described in <xref target="RFC86 20" section="5.6" sectionFormat="of"></xref>.</t> | |||
</section> | </section> | |||
<section anchor="contactcard-set"><name>ContactCard/set</name> | <section anchor="contactcard-set"><name>ContactCard/set</name> | |||
<t>This is a standard "/set" method as described in <xref target="RFC8620" secti | <t>This is a standard "/set" method as described in <xref target="RFC8620" secti | |||
on="5.3" sectionFormat="comma"></xref>.</t> | on="5.3" sectionFormat="of"></xref>.</t> | |||
<t>To set a new photo, the file must first be uploaded using the upload mechanis | <t>To set a new photo, the file must first be uploaded using the upload mechanis | |||
m as described in <xref target="RFC8620" section="6.1" sectionFormat="comma"></x | m as described in <xref target="RFC8620" section="6.1" sectionFormat="of"></xref | |||
ref>. This will give the client a valid blobId/size/type to use. The server MUST | >. This will give the client a valid blobId, size, and type to use. The server < | |||
reject attempts to set a file that is not a recognised image type as the photo | bcp14>MUST</bcp14> reject attempts to set a file that is not a recognised image | |||
for a card.</t> | type as the photo for a card.</t> | |||
</section> | </section> | |||
<section anchor="contactcard-copy"><name>ContactCard/copy</name> | <section anchor="contactcard-copy"><name>ContactCard/copy</name> | |||
<t>This is a standard "/copy" method as described in <xref target="RFC8620" sect ion="5.4" sectionFormat="comma"></xref>.</t> | <t>This is a standard "/copy" method as described in <xref target="RFC8620" sect ion="5.4" sectionFormat="of"></xref>.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="examples"><name>Examples</name> | <section anchor="examples"><name>Examples</name> | |||
<t>For brevity, in the following examples only the "methodCalls" property of the Request object, and the "methodResponses" property of the Response object is sh own.</t> | <t>For brevity, only the "methodCalls" property of the Request object and the "m ethodResponses" property of the Response object is shown in the following exampl es.</t> | |||
<section anchor="fetching-initial-data"><name>Fetching initial data</name> | <section anchor="fetching-initial-data"><name>Fetching Initial Data</name> | |||
<t>A user has authenticated and the client has fetched the JMAP Session object. | <t>A user has authenticated and the client has fetched the JMAP Session object. | |||
It finds a single Account with the "urn:ietf:params:jmap:contacts" capability, w | It finds a single Account with the "urn:ietf:params:jmap:contacts" capability wi | |||
ith id "a0x9", and wants to fetch all the address books and contacts. It might m | th id "a0x9" and wants to fetch all the address books and contacts. It might mak | |||
ake the following request:</t> | e the following request:</t> | |||
<artwork>[ | <figure> | |||
<name>"methodCalls" Property of a JMAP Request</name> | ||||
<sourcecode type="json">[ | ||||
["AddressBook/get", { | ["AddressBook/get", { | |||
"accountId": "a0x9" | "accountId": "a0x9" | |||
}, "0"], | }, "0"], | |||
["ContactCard/get", { | ["ContactCard/get", { | |||
"accountId": "a0x9" | "accountId": "a0x9" | |||
}, "1"] | }, "1"] | |||
] | ]</sourcecode> | |||
</artwork> | </figure> | |||
<t>The server might respond with something like:</t> | <t>The server might respond with something like:</t> | |||
<artwork>[ | <figure> | |||
<name>"methodResponses" Property of a JMAP Response</name> | ||||
<sourcecode type="json">[ | ||||
["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"] | |||
] | ]</sourcecode> | |||
</artwork> | </figure> | |||
</section> | </section> | |||
<section anchor="changing-the-default-address-book"><name>Changing the default a ddress book</name> | <section anchor="changing-the-default-address-book"><name>Changing the Default A ddress Book</name> | |||
<t>The client tries to change the default address book from "Personal" to "Autos aved" (and makes no other change):</t> | <t>The client tries to change the default address book from "Personal" to "Autos aved" (and makes no other change):</t> | |||
<artwork>[ | <figure> | |||
<name>"methodCalls" Property of a JMAP Request</name> | ||||
<sourcecode type="json">[ | ||||
["AddressBook/set", { | ["AddressBook/set", { | |||
"accountId": "a0x9", | "accountId": "a0x9", | |||
"onSuccessSetIsDefault": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe" | "onSuccessSetIsDefault": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe" | |||
}, "0"] | }, "0"] | |||
] | ]</sourcecode> | |||
</artwork> | </figure> | |||
<t>The server allows the change, returning the following response:</t> | <t>The server allows the change, returning the following response:</t> | |||
<artwork>[ | <figure> | |||
<name>"methodResponses" Property of a JMAP Response</name> | ||||
<sourcecode type="json">[ | ||||
["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"] | |||
] | ]</sourcecode> | |||
</artwork> | </figure> | |||
</section> | </section> | |||
</section> | </section> | |||
<section><name>Internationalisation Considerations</name> | <section><name>Internationalisation Considerations</name> | |||
<t>Experience has shown that unrestricted use of Unicode can lead to problems su | <t>Experience has shown that unrestricted use of Unicode can lead to problems su | |||
ch as inconsistent rendering, users reading text and interpreting it differently | ch as inconsistent rendering, users reading text and interpreting it differently | |||
than intended, and unexpected results when copying text from one location to an | than intended, and unexpected results when copying text from one location to an | |||
other. Servers MAY choose to mitigate this by restricting the set of characters | other. Servers <bcp14>MAY</bcp14> choose to mitigate this by restricting the set | |||
allowed in otherwise unconstrained <tt>String</tt> fields. The FreeformClass, as | of characters allowed in otherwise unconstrained <tt>String</tt> fields. The Fr | |||
documented in <xref target="RFC8264" section="4.3" sectionFormat="comma" /> mig | eeformClass, as documented in <xref target="RFC8264" section="4.3" sectionFormat | |||
ht be a good starting point for this.</t> | ="of"/>, might be a good starting point for | |||
<t>Attempts to set a value containing code points outside of the permissible set | this.</t> | |||
can be handled in a few ways by the server. The server could choose to strip th | ||||
e forbidden characters, or replace them with U+FFFD (the Unicode replacement cha | <t>Attempts to set a value containing code points outside of the permissible set | |||
racter), and store the resulting string. This is likely to be appropriate for no | can be handled in a few ways by the server. The server could choose to strip th | |||
n-printable characters — such as the "Control Codes" defined in <xref target="UN | e forbidden characters or replace them with U+FFFD (the Unicode replacement char | |||
ICODE"/> Section 23.1, excluding newline (U+000A), carriage return (U+000D), and | acter) and store the resulting string. This is likely to be appropriate for non- | |||
tab (U+0009) — which can end up in data accidentally due to copy-and-paste issu | printable characters -- such as the "Control Codes" defined in <eref target="htt | |||
es, but are invisible to the end user. JMAP allows the server to transform data | ps://www.unicode.org/versions/latest/core-spec/chapter-23/#G20365">Section 23.1< | |||
on create/update, as long as any changed properties are returned to the client i | /eref> of <xref target="UNICODE"/>, excluding newline (U+000A), carriage return | |||
n the <tt>/set</tt> response, so it knows what has changed, as per <xref target= | (U+000D), and tab (U+0009) -- that can end up in data accidentally due to copy-a | |||
"RFC8620" section="5.3" sectionFormat="comma" />. Alternatively, the server MAY | nd-paste issues but are invisible to the end user. JMAP allows the server to tra | |||
just reject the create/update with an <tt>invalidProperties</tt> SetError.</t> | nsform data on create/update as long as any changed properties are returned to t | |||
he client in the "/set" response so it knows what has changed, as per <xref targ | ||||
et="RFC8620" section="5.3" sectionFormat="of" />. Alternatively, the server <bcp | ||||
14>MAY</bcp14> just reject the create/update with an "invalidProperties" SetErro | ||||
r.</t> | ||||
</section> | </section> | |||
<section anchor="security-considerations"><name>Security Considerations</name> | <section anchor="security-considerations"><name>Security Considerations</name> | |||
<t>All security considerations of JMAP (<xref target="RFC8620"></xref>) apply to | <t>All security considerations of JMAP <xref target="RFC8620"></xref> apply to t | |||
this specification. Additional considerations specific to the data types and fu | his specification. Additional considerations specific to the data types and func | |||
nctionality introduced by this document are described in the following subsectio | tionality introduced by this document are described in the following subsection. | |||
n.</t> | </t> | |||
<t>Contacts consist almost entirely of private, personally identifiable informat | <t>Contacts consist almost entirely of private, personally identifiable informat | |||
ion, and represent the social connections of users. Privacy leaks can have real | ion, and represent the social connections of users. Privacy leaks can have real | |||
world consequences, and contacts servers and clients MUST be mindful of the need | world consequences, and contact servers and clients <bcp14>MUST</bcp14> be mindf | |||
to keep all data secure.</t> | ul of the need to keep all data secure.</t> | |||
<t>Servers MUST enforce the ACLs set on address books to ensure only authorised | <t>Servers <bcp14>MUST</bcp14> enforce the Access Control Lists (ACLs) set on ad | |||
data is shared.</t> | dress books to ensure only authorised data is shared.</t> | |||
</section> | </section> | |||
<section anchor="iana-considerations"><name>IANA Considerations</name> | <section anchor="iana-considerations"><name>IANA Considerations</name> | |||
<section anchor="jmap-capability-registration-for-contacts"><name>JMAP capabilit | <section anchor="jmap-capability-registration-for-contacts"><name>JMAP Capabilit | |||
y registration for "contacts"</name> | y Registration for "contacts"</name> | |||
<t>IANA will register "contacts" in the "JMAP Capabilities" registry as follows: | <t>IANA has registered "contacts" in the "JMAP Capabilities" registry as follows | |||
</t> | :</t> | |||
<t>Capability Name: <tt>urn:ietf:params:jmap:contacts</tt></t> | ||||
<t>Specification document: this document</t> | <dl newline="false" spacing="compact"> | |||
<t>Intended use: common</t> | <dt>Capability Name:</dt><dd><tt>urn:ietf:params:jmap:contacts</tt></dd> | |||
<t>Change Controller: IETF</t> | <dt>Intended Use:</dt><dd>common</dd> | |||
<t>Security and privacy considerations: this document, <xref target="security-co | <dt>Change Controller:</dt><dd>IETF</dd> | |||
nsiderations" /></t> | <dt>Security and Privacy Considerations:</dt><dd>this document, <xref target=" | |||
security-considerations" /></dd> | ||||
<dt>Reference:</dt><dd>this document</dd> | ||||
</dl> | ||||
</section> | </section> | |||
<section anchor="jmap-data-type-registration-for-addressbook"><name>JMAP Data Ty pe Registration for "AddressBook"</name> | <section anchor="jmap-data-type-registration-for-addressbook"><name>JMAP Data Ty pe Registration for "AddressBook"</name> | |||
<t>IANA will register "AddressBook" in the "JMAP Data Types" registry as follows | <t>IANA has registered "AddressBook" in the "JMAP Data Types" registry as follow | |||
:</t> | s:</t> | |||
<t>Type Name: <tt>AddressBook</tt></t> | <dl newline="false" spacing="compact"> | |||
<t>Can reference blobs: no</t> | <dt>Type Name:</dt><dd><tt>AddressBook</tt></dd> | |||
<t>Can Use for State Change: yes</t> | <dt>Can Reference Blobs:</dt><dd>No</dd> | |||
<t>Capability: <tt>urn:ietf:params:jmap:contacts</tt></t> | <dt>Can Use for State Change:</dt><dd>Yes</dd> | |||
<t>Specification document: this document</t> | <dt>Capability:</dt><dd><tt>urn:ietf:params:jmap:contacts</tt></dd> | |||
<dt>Reference:</dt><dd>this document</dd> | ||||
</dl> | ||||
</section> | </section> | |||
<section anchor="jmap-data-type-registration-for-contactcard"><name>JMAP Data Ty pe Registration for "ContactCard"</name> | <section anchor="jmap-data-type-registration-for-contactcard"><name>JMAP Data Ty pe Registration for "ContactCard"</name> | |||
<t>IANA will register "ContactCard" in the "JMAP Data Types" registry as follows | <t>IANA has registered "ContactCard" in the "JMAP Data Types" registry as follow | |||
:</t> | s:</t> | |||
<t>Type Name: <tt>ContactCard</tt></t> | ||||
<t>Can reference blobs: yes</t> | <dl newline="false" spacing="compact"> | |||
<t>Can Use for State Change: yes</t> | <dt>Type Name:</dt><dd><tt>ContactCard</tt></dd> | |||
<t>Capability: <tt>urn:ietf:params:jmap:contacts</tt></t> | <dt>Can Reference Blobs:</dt><dd>Yes</dd> | |||
<t>Specification document: this document</t> | <dt>Can Use for State Change:</dt><dd>Yes</dd> | |||
<dt>Capability:</dt><dd><tt>urn:ietf:params:jmap:contacts</tt></dd> | ||||
<dt>Reference:</dt><dd>this document</dd> | ||||
</dl> | ||||
</section> | </section> | |||
<section anchor="jmap-error-codes-registry" title="JMAP Error Codes Registry"> | <section anchor="jmap-error-codes-registry" title="JMAP Error Codes Registry"> | |||
<t>The following subsection registers a new error code in the "JMAP | <t>The following subsection has registered a new error code in the "JMAP | |||
Error Codes" registry, as defined in <xref target="RFC8620" section="9"/>. | Error Codes" registry, as defined in <xref target="RFC8620" section="9"/>. | |||
</t> | </t> | |||
<section anchor="addressbookhascontents" title="addressBookHasContents"> | <section anchor="addressbookhascontents" title="addressBookHasContents"> | |||
<t>JMAP Error Code: addressBookHasContents</t> | <dl newline="false" spacing="compact"> | |||
<t>Intended use: common</t> | <dt>JMAP Error Code:</dt><dd>addressBookHasContents</dd> | |||
<t>Change controller: IETF</t> | <dt>Intended Use:</dt><dd>common</dd> | |||
<t>Reference: This document, <xref target="addressbook-set"/></t> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<t>Description: The AddressBook has at least one ContactCard assigned to it, and | <dt>Description:</dt><dd>The AddressBook has at least one ContactCard assigned t | |||
the "onDestroyRemoveContents" argument was false.</t> | o it, and the "onDestroyRemoveContents" argument was false.</dd> | |||
<dt>Reference:</dt><dd>This document, <xref target="addressbook-set"/></dd> | ||||
</dl> | ||||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="jscontact-property-registrations"> | <section anchor="jscontact-property-registrations"> | |||
<name>JSContact Property Registrations</name> | <name>JSContact Property Registrations</name> | |||
<t>IANA will register the following additional properties in the JSContact Prope rties Registry, as defined in <xref target="RFC9553" section="3"/>.</t> | <t>IANA has registered the following additional properties in the "JSContact Pro perties" registry, as defined in <xref target="RFC9553" section="3"/>.</t> | |||
<section anchor="id"><name>id</name> | <section anchor="id"><name>id</name> | |||
<t>Property Name: id</t> | <dl newline="false" spacing="compact"> | |||
<t>Property Type: Not applicable</t> | <dt>Property Name:</dt><dd>id</dd> | |||
<t>Property Context: Card</t> | <dt>Property Type:</dt><dd>not applicable</dd> | |||
<t>Intended Use: Reserved</t> | <dt>Property Context:</dt><dd>Card</dd> | |||
<t>Since Version: 1.0</t> | <dt>Intended Usage:</dt><dd>reserved</dd> | |||
<t>Change Controller: IETF</t> | <dt>Since Version:</dt><dd>1.0</dd> | |||
<dt>Change Controller:</dt><dd>IETF</dd> | ||||
<dt>Reference:</dt><dd>this document</dd> | ||||
</dl> | ||||
</section> | </section> | |||
<section anchor="addressBookIds"><name>addressBookIds</name> | <section anchor="addressBookIds"><name>addressBookIds</name> | |||
<t>Property Name: addressBookIds</t> | <dl newline="false" spacing="compact"> | |||
<t>Property Type: Not applicable</t> | <dt>Property Name:</dt><dd>addressBookIds</dd> | |||
<t>Property Context: Card</t> | <dt>Property Type:</dt><dd>not applicable</dd> | |||
<t>Intended Use: Reserved</t> | <dt>Property Context:</dt><dd>Card</dd> | |||
<t>Since Version: 1.0</t> | <dt>Intended Usage:</dt><dd>reserved</dd> | |||
<t>Change Controller: IETF</t> | <dt>Since Version:</dt><dd>1.0</dd> | |||
<dt>Change Controller:</dt><dd>IETF</dd> | ||||
<dt>Reference:</dt><dd>this document</dd> | ||||
</dl> | ||||
</section> | </section> | |||
<section anchor="blobId"><name>blobId</name> | <section anchor="blobId"><name>blobId</name> | |||
<t>Property Name: blobId</t> | <dl newline="false" spacing="compact"> | |||
<t>Property Type: Not applicable</t> | <dt>Property Name:</dt><dd>blobId</dd> | |||
<t>Property Context: Media</t> | <dt>Property Type:</dt><dd>not applicable</dd> | |||
<t>Intended Use: Reserved</t> | <dt>Property Context:</dt><dd>Media</dd> | |||
<t>Since Version: 1.0</t> | <dt>Intended Usage:</dt><dd>reserved</dd> | |||
<t>Change Controller: IETF</t> | <dt>Since Version:</dt><dd>1.0</dd> | |||
<dt>Change Controller:</dt><dd>IETF</dd> | ||||
<dt>Reference:</dt><dd>this document</dd> | ||||
</dl> | ||||
</section> | </section> | |||
</section> | </section> | |||
</section> | </section> | |||
</middle> | </middle> | |||
<back> | <back> | |||
<references> | ||||
<name>References</name> | ||||
<references><name>Normative References</name> | <references><name>Normative References</name> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml" /> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml" /> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2397.xml" /> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2397.xml" /> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml" /> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml" /> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8620.xml" /> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8620.xml" /> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9553.xml" /> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9553.xml" /> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-jma p-sharing.xml"/> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9670.xml" /> | |||
</references> | </references> | |||
<references><name>Informative References</name> | <references><name>Informative References</name> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8264. | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8264.xml" | |||
xml"/> | /> | |||
<reference anchor="UNICODE" target="http://www.unicode.org/versions/latest/"> | <reference anchor="UNICODE" target="https://www.unicode.org/versions/latest/"> | |||
<front> | <front> | |||
<title abbrev="Unicode">The Unicode Standard</title> | <title abbrev="Unicode">The Unicode Standard</title> | |||
<author><organization>The Unicode Consortium</organization><address /></author> | <author><organization>The Unicode Consortium</organization><address /></author> | |||
</front> | </front> | |||
<annotation>Note that this 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.</annotation> | ||||
</reference> | </reference> | |||
</references> | ||||
</references> | ||||
</references> | ||||
</back> | </back> | |||
</rfc> | </rfc> | |||
End of changes. 75 change blocks. | ||||
479 lines changed or deleted | 527 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. |