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 "&#160;">
ietf-jmap-contacts-10" stream="IETF" status="standard" name="Internet-Draft"></s <!ENTITY zwsp "&#8203;">
eriesInfo> <!ENTITY nbhy "&#8209;">
<author role="editor" initials="N.M." surname="Jenkins" fullname="Neil Jenkins"> <!ENTITY wj "&#8288;">
<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&nbsp;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 &gt;= 1, or null for no limit (or rather, the limit />). This <bcp14>MUST</bcp14> be an integer &gt;= 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 &lt;= sortOrder &lt; 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 &lt;= sortOrder &lt; 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.