Return-Path: <neilj@fastmailteam.com>
X-Original-To: jmap@mail2.ietf.org
Delivered-To: jmap@mail2.ietf.org
Received: from localhost (localhost [127.0.0.1])
	by mail2.ietf.org (Postfix) with ESMTP id EF79BDC7CB91
	for <jmap@mail2.ietf.org>; Tue, 14 Apr 2026 21:51:58 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ietf.org; s=ietf1;
	t=1776228719; bh=Bq/imW38zXkssyUXthUsc+6VNEP7/BjHQZylNXTRmb8=;
	h=Date:From:To:In-Reply-To:References:Subject;
	b=MarAKXo8Irx1UKk0GsMOIy5bXtPFemjJBGL+BM5hvc+cr9f3QVRl+p7QA+sWbVYzg
	 CWYbq4sEgGBYlAMaizpWi2ovH9N3qHS3WKCMxgZafsvOVL4T4buQ4dq/fqtZ93ehFq
	 A6X0s+eDeLQdF+z2EGzvXcOXkHYnpwmg9woRjN2c=
X-Virus-Scanned: amavisd-new at ietf.org
X-Spam-Flag: NO
X-Spam-Score: -2.797
X-Spam-Level: 
X-Spam-Status: No, score=-2.797 tagged_above=-999 required=5
	tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1,
	DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001,
	RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=0.001,
	RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001,
	RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_PASS=-0.001]
	autolearn=ham autolearn_force=no
Authentication-Results: mail2.ietf.org (amavisd-new); dkim=pass (2048-bit key)
	header.d=fastmailteam.com header.b="KL2Z56OI";
	dkim=pass (2048-bit key) header.d=messagingengine.com
	header.b="I+ZOz+qT"
Received: from mail2.ietf.org ([166.84.6.31])
	by localhost (mail2.ietf.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id 6KDs86MSLT4F for <jmap@mail2.ietf.org>;
	Tue, 14 Apr 2026 21:51:57 -0700 (PDT)
Received: from fout-a3-smtp.messagingengine.com
 (fout-a3-smtp.messagingengine.com [103.168.172.146])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature ECDSA (P-256) server-digest SHA256)
	(No client certificate requested)
	by mail2.ietf.org (Postfix) with ESMTPS id AFF43DC7CB11
	for <jmap@ietf.org>; Tue, 14 Apr 2026 21:51:52 -0700 (PDT)
Received: from phl-compute-10.internal (phl-compute-10.internal [10.202.2.50])
	by mailfout.phl.internal (Postfix) with ESMTP id 64379EC00C4
	for <jmap@ietf.org>; Wed, 15 Apr 2026 00:51:45 -0400 (EDT)
Received: from phl-imap-15 ([10.202.2.104])
  by phl-compute-10.internal (MEProxy); Wed, 15 Apr 2026 00:51:45 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
	fastmailteam.com; h=cc:content-type:content-type:date:date:from
	:from:in-reply-to:in-reply-to:message-id:mime-version:references
	:reply-to:subject:subject:to:to; s=fm3; t=1776228705; x=
	1776315105; bh=x+QZcNofofb66WY8Pnjv7agb72lQx9N37HeBA5Wh6AI=; b=K
	L2Z56OIPUZRwWaUQJPLVNGM6Y9p3zx1CuN9NGHl3T027mofW8vAfkTKA6cWh9uhq
	MG0omBlz6N0A2a9wQwdmo7wr6UPXsThSSj0f2ihBVeAY+ljjOIClyh2hkXVm+qXU
	g3IJgV9agbPu48VOnlCt1ROXqZNNrMOEA1JYCSxuxg453RHN/knY4fDFgizEesn9
	/SI7xD18ojQfKrVLT6cOUxi4pvueKPq0TiLL4pyp/eicOsC1sy8GByV5BCA5dmsN
	EqgHuqc1rptp1x/PibpesqqaMPiUyh4eJ+Pk0FVj+lr3stDJH+vEUvJX5S2tJkwg
	3Xd+ivFnsdCrxFhLCEoIw==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
	messagingengine.com; h=cc:content-type:content-type:date:date
	:feedback-id:feedback-id:from:from:in-reply-to:in-reply-to
	:message-id:mime-version:references:reply-to:subject:subject:to
	:to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=
	1776228705; x=1776315105; bh=x+QZcNofofb66WY8Pnjv7agb72lQx9N37He
	BA5Wh6AI=; b=I+ZOz+qTROoa18tvrBIK0eGH4XnQxkNJDMAuTrtfTBsYTwI3A3Q
	PEP9ab/CA1LhxtBSk3Uj2HvdIG4V1EU0XceN0WVWpt7T2gLW7gOZnFkF6vQMqgSj
	o7Q7yuRVtVlJyKA25z/oJUlebdw8Vlqe6YS6u15t+BYrH6snUiAs1MZPIRC6hnuv
	oy/3gEnvD04ykkMFzmWbi+YFLzraPJuGlbA6rZtBBtqxi3md0CDCo9hKkGBYhlL0
	MRhYhMTX0Gz8PY3C/GWunnsCcslDJmltAcAqIzF9mhVpIaLH94mkujEsGCtf83VY
	YswOnvFfh25tfPlWqLeyaKapnI3NIMHgbfw==
X-ME-Sender: <xms:YRnfaUoBPK0wshD-UnvDx2MRvFe6yfiDZgZuabuii8OwkrwPPMZsLg>
    <xme:YRnfaVfce-Nlcpa432q-jbrKKQzsXCbq2PPzVvtAekroDBkslh9mqUlK_AbXlHMUO
    __g2F95U0WynIS3nIM1oBnD4BWSHf9VWm5a8O2ml1gM_wNhmw>
X-ME-Proxy-Cause: 
 gggruggvucftvghtrhhoucdtuddrgeefhedrtddtgdegfeduhecutefuodetggdotefrod
    ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpuffrtefokffrpgfnqfghnecuuegr
    ihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjug
    hrpefoggffhffvkfgjfhfutgesrgdtreerredtjeenucfhrhhomhepfdfpvghilhculfgv
    nhhkihhnshdfuceonhgvihhljhesfhgrshhtmhgrihhlthgvrghmrdgtohhmqeenucggtf
    frrghtthgvrhhnpeeijeevjedtgeejfeeluddtheekveeihffgueduteevueekgeetudeg
    ueffleeghfenucffohhmrghinhepihgvthhfrdhorhhgpdhfrghsthhmrghilhdrtghomh
    dprhhftgdqvgguihhtohhrrdhorhhgnecuvehluhhsthgvrhfuihiivgeptdenucfrrghr
    rghmpehmrghilhhfrhhomhepnhgvihhljhesfhgrshhtmhgrihhlthgvrghmrdgtohhmpd
    hnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehjmhgr
    phesihgvthhfrdhorhhg
X-ME-Proxy: <xmx:YRnfaaPrmKt1-v1IQCDzprtI3Lf6QQjUf9X7-ZS-oWDL9WE2ek2HXw>
    <xmx:YRnfaf7atK4gtMYuQqgVtat3S-65nsDC1XGQDI8jFme2sQHiXQYOLA>
    <xmx:YRnfaW7dC4KHNzUkoRlaE8pAtcJWS1zVT6eut1w6nfS-gbhw9d2KFw>
    <xmx:YRnfaf2c2_UjK9juXoFa4GJqaGampap7vr1Y-iLERxmQUwRizYNCzA>
    <xmx:YRnfadGmqot1eOMYyC3G3Z4VvgSMCR8NKjlbwt5G4pz65grwkfmpCwDJ>
Feedback-ID: ibc614277:Fastmail
Received: by mailuser.phl.internal (Postfix, from userid 501)
	id 1604A780070; Wed, 15 Apr 2026 00:51:45 -0400 (EDT)
X-Mailer: MessagingEngine.com Webmail Interface
MIME-Version: 1.0
Date: Wed, 15 Apr 2026 14:50:45 +1000
From: "Neil Jenkins" <neilj@fastmailteam.com>
To: "JMAP IETF" <jmap@ietf.org>
Message-Id: <9e8b403c-e0d3-4af6-ac47-c1af06f27e1e@dogfoodapp.fastmail.com>
In-Reply-To: <8397988B-24C5-42D7-BD1E-45CEDD009AC5@stalw.art>
References: <8397988B-24C5-42D7-BD1E-45CEDD009AC5@stalw.art>
Content-Type: multipart/alternative;
 boundary=6a26f77ea7d22c06368dfcfd8932afc2156f1737
Message-ID-Hash: WVSUFW7X6ITGQBUKWROVM5XINS5XQGRZ
X-Message-ID-Hash: WVSUFW7X6ITGQBUKWROVM5XINS5XQGRZ
X-MailFrom: neilj@fastmailteam.com
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency;
 loop; banned-address; member-moderation; header-match-jmap.ietf.org-0;
 nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size;
 news-moderation; no-subject; digests; suspicious-header
X-Mailman-Version: 3.3.9rc6
Precedence: list
Subject: =?utf-8?q?=5BJMAP=5D_Re=3A_Status_of_JMAP_Metadata=2C_RefPlus_and_Mail_Shari?=
 =?utf-8?q?ng_drafts_ahead_of_IETF_125?=
List-Id: JSON Meta Access Protocol <jmap.ietf.org>
Archived-At: 
 <https://mailarchive.ietf.org/arch/msg/jmap/jKJw9Zk3-82Sid3Qzld7Jebfd6I>
List-Archive: <https://mailarchive.ietf.org/arch/browse/jmap>
List-Help: <mailto:jmap-request@ietf.org?subject=help>
List-Owner: <mailto:jmap-owner@ietf.org>
List-Post: <mailto:jmap@ietf.org>
List-Subscribe: <mailto:jmap-join@ietf.org>
List-Unsubscribe: <mailto:jmap-leave@ietf.org>

--6a26f77ea7d22c06368dfcfd8932afc2156f1737
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

I've read through all of these again.

> https://datatracker.ietf.org/doc/draft-ietf-jmap-mail-sharing/

This looks great, I think it should go to WG last call and be submitted =
for publication.

> https://datatracker.ietf.org/doc/draft-ietf-jmap-refplus/

My overall view of this is still that the added complexity (and executio=
n performance concerns) of this outweighs the performance benefits of re=
ducing a few extra round trips. I'm not objecting to the document moving=
 forward, but I'd love to see some evidence that someone has a real use =
case for it. Regardless, some more specific concerns:

**=C2=A71.2.1. The value of this property in the JMAP Session "accountCa=
pabilities" property is an empty object.**

I don't think the capability should be included in `accountCapabilities`=
, just the top-level `capabilities`. These changes are not things within=
 a particular account; they apply at a higher level (like JMAP Core). (C=
aveat, see comment on /set below.)
*
*
**=C2=A72.2.1 The nodelist produced by JSON Path evaluation MUST be reso=
lved according to the expected type of the target property**

I *really* don't like this. Instead of being a pure syntactical transfor=
mation, the dispatching server must now understand the full expected str=
ucture of the method being called in order to apply the result reference=
. This is a layering violation, and could be impossible for a generic JM=
AP proxy that doesn't understand (or need to understand) the actual meth=
od calls it's dispatching to JMAP servers downstream.

(Yes, I saw later in =C2=A73.1 you say *"The type-specific resolution ru=
les defined in this specification (determining whether a resolved value =
should be treated as a single value, an array, or a map) are applied by =
the JMAP method implementation layer, not by the reference resolution la=
yer."* =E2=80=94 that's still requiring support at multiple layers.)

Instead, why not add an extra `type` property to the ResultReference obj=
ect that gives the expected type? The caller should know what they expec=
t this to resolve to, and that means the reference resolver doesn't need=
 to know. This lets everything be done at the Syntactic Resolution Phase=
 (per =C2=A73.2).

**=C2=A72.3 Usage in /set Methods**

I think we need to explicitly state that should you opt in to the refplu=
s capability you *cannot *set a property within a Foo object that beings=
 with a literal `#`. This is not a problem with any of the data types be=
ing used with JMAP so far (as far as I'm aware), but worth noting for th=
e future. (If for some reason a client *does* need to do this in the fut=
ure, they must not include the refplus capability in the `using` array o=
f the Request object; as per RFC8620, if not explicitly opted in, the se=
rver must not apply the capability.)

**=C2=A72.3**** If a result reference fails to resolve, the server MUST =
reject the creation or update of that specific object with a SetError of=
 type "invalidResultReference"**

This is problematic, because it means the resolution has to happen at me=
thod execution time, rather than at method dispatch time. I don't think =
it's necessary: we can resolve the references before dispatch and reject=
 the whole method with `invalidResultReference` if any fail. That's cons=
istent with all the other result reference resolution, and means it can =
be handled in the same layer.

Otherwise, if we really want to keep the currently specified behaviour, =
I think we will need to add the refplus capability to the `accountCapabi=
lities` of accounts that support using ResultReferences inside `/set` cr=
eate/update. Again, in the proxy case it may not be all of them.

> https://datatracker.ietf.org/doc/draft-ietf-jmap-metadata/

I think this is looking fairly solid. A few comments:

**=C2=A72.1.2 Servers SHOULD document whether they provide read-only or =
read-write access to ImapMetadata.**
**=C2=A72.1.3 **Servers SHOULD document whether they provide read-only o=
r read-write access to WebDavMetadata.****

Why not put this in the capabilities?

**=C2=A7***3.1 "alreadyExists" SetError [=E2=80=A6] MAY include an "exis=
tingId" property containing the id of the existing Metadata object.*

I'd change this MAY to a MUST =E2=80=94 it's easy to implement, and if i=
t's only a MAY a client can't rely on it, which is a pain. (As a general=
 rule,=20

**=C2=A74.1 The response to an extended /get method includes the followi=
ng additional property**

I think we probably need to include `metadataState` in the response as w=
ell?
**
**
**=C2=A74.2.1 Servers SHOULD NOT generate [=E2=80=A6] state changes for =
automatically deleted metadata. The deletion is considered an implicit c=
onsequence of destroying the related object. However, servers MAY emit p=
ush notifications or update metadata state strings to reflect that metad=
ata has been deleted, if such notifications would otherwise occur for ex=
plicitly deleted metadata.**

I'm not quite sure what you're going for here. Surely the metadata state=
 *has* to change if a metadata object is destroyed, regardless of how th=
is happened. Otherwise, the `/changes` updates won't work correctly.

Related, the document doesn't currently specify that changes purely to a=
 Metadata object SHOULD NOT change the state string for the related type=
, but I think that's the idea. Although=E2=80=A6

*Is this the right approach?*

With my client implementer hat on, I was thinking about how I would want=
 to use metadata. Generally, I'd want to be able to say "I'm interested =
in metadata for this particular type" and then fetch/update it with the =
instances of that type themselves. I can't think of a circumstance where=
 I'd want metadata without the related object, but I could definitely ju=
st have a small subset of the dataset for a particular object (e.g. I ha=
ve loaded 100 emails for a user with 1,000,000 messages). The current ap=
proach is a bit painful:
 =E2=80=A2 I can fetch the metadata with the Email objects by using the =
*fetchMetadata* argument. Fine.
 =E2=80=A2 The Metadata state changes. I call `Metadata/changes` with *f=
ilterRelatedType* set to `"Email"`. I can ignore any *updated* metadata =
objects I don't have, but I have to always fetch the *created* metadata =
objects, as I have no way of knowing if they're related to the Email obj=
ects I currently have in memory or not.
 =E2=80=A2 I can't search for a Foo object that has some particular meta=
data AND a regular property (e.g. if I used metadata to store a memo <ht=
tps://www.fastmail.com/features/memos/> on an Email, and wanted to searc=
h for all emails that are in the inbox and have a memo with the text "fo=
o").
A very different approach would be:
 =E2=80=A2 Data types with metadata support (as per the capabilities) ge=
t a mutable `_metadata_: String[*]` property if you opt in to the capabi=
lity. We could have a `_private_metadata_` property too for private meta=
data, if supported (per the capability).=20
 =E2=80=A2 The value of this property is a (possibly empty) object (neve=
r null so you can always patch). The keys at the top level are registere=
d, or a domain name:
   =E2=80=A2 `imap`: maps to IMAP metadata
   =E2=80=A2 `webdav`: maps to WebDAV metadata
   =E2=80=A2 `example.com`: maps to arbitrary vendor data.
 =E2=80=A2 The metadata property can be specified in the *properties* ar=
gument to `Foo/get`, like any other property. If you don't specify any p=
roperties, it will be returned with the default set of properties (norma=
lly everything) for that data type. (Or maybe we'd need a way to say "gi=
ve me all the default properties, but *not* the metadata properties for =
this object type"?)
 =E2=80=A2 `Foo/changes` returns objects where the `_metadata_` property=
 has changed in the *updated* argument of the response. We add an *updat=
edProperties* argument to the response, like in Mailbox/changes <https:/=
/www.rfc-editor.org/rfc/rfc8621.html#section-2.2>. If only metadata has =
changed, the server should use this to indicate that, so you can then on=
ly fetch the metadata property. Possibly we add an extra argument to `Fo=
o/changes` to ignore metadata-only changes for data types where you're n=
ot interested in the metadata.
 =E2=80=A2 We define some extensions to the `Foo/query` FilterCondition =
for any data type that supports metadata:
   =E2=80=A2 the presence of metadata at a particular path, e.g., `{"met=
adataExists": "fastmail.com/memo"}` =E2=80=94 this matches any object wh=
ere it has a value defined at that path.
   =E2=80=A2 text match at a particular path. e.g., `{"metadataText": { =
path: "fastmail.com/memo", value: "foo"}` =E2=80=94 looks for a string i=
n the property at a particular path. Is false if the path doesn't exist =
or isn't a string type.
 =E2=80=A2 That's =E2=80=A6 kind of it? You can use standard `Foo/set` p=
atching to update specific metadata properties without stomping on other=
 vendors=E2=80=99 metadata. You always keep your metadata in sync with t=
he underlying objects. You don't really need to change any code in the c=
lient, and all existing sync code will just work.
Thoughts? This seems both simpler and more functional to me, and I don't=
 see any obvious drawbacks at first glance.

Cheers,
Neil.
--6a26f77ea7d22c06368dfcfd8932afc2156f1737
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html><html><head><title></title></head><body><div>I've read th=
rough all of these again.</div><div><br></div><blockquote type=3D"cite">=
<div><a href=3D"https://datatracker.ietf.org/doc/draft-ietf-jmap-mail-sh=
aring/">https://datatracker.ietf.org/doc/draft-ietf-jmap-mail-sharing/</=
a><br></div></blockquote><div><br></div><div>This looks great, I think i=
t should go to WG last call and be submitted for publication.</div><div>=
<br></div><blockquote type=3D"cite"><div><a href=3D"https://datatracker.=
ietf.org/doc/draft-ietf-jmap-refplus/">https://datatracker.ietf.org/doc/=
draft-ietf-jmap-refplus/</a><br></div></blockquote><div><br></div><div>M=
y overall view of this is still that the added complexity (and execution=
 performance concerns) of this outweighs the performance benefits of red=
ucing a few extra round trips. I'm not objecting to the document moving =
forward, but&nbsp;I'd love to see some evidence that someone has a real =
use case for it. Regardless, some more specific concerns:</div><div><br>=
</div><div><b><i>=C2=A71.2.1.&nbsp;The value of this property in the JMA=
P Session "accountCapabilities" property is an empty object.</i></b><br>=
</div><div><br></div><div>I don't think the capability should be include=
d in <code style=3D"border-top-width:1px;border-top-style:solid;border-t=
op-color:rgb(204, 204, 204);border-right-width:1px;border-right-style:so=
lid;border-right-color:rgb(204, 204, 204);border-bottom-width:1px;border=
-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);border-left-w=
idth:1px;border-left-style:solid;border-left-color:rgb(204, 204, 204);bo=
rder-image-outset:0;border-image-repeat:stretch;border-image-slice:100%;=
border-image-source:none;border-image-width:1;border-top-left-radius:3px=
;border-top-right-radius:3px;border-bottom-right-radius:3px;border-botto=
m-left-radius:3px;background-color:rgb(246, 246, 246);background-positio=
n-x:0%;background-position-y:0%;background-repeat:repeat;background-atta=
chment:scroll;background-image:none;background-size:auto;background-orig=
in:padding-box;background-clip:border-box;font-family:menlo, consolas, m=
onospace;font-size:90%;padding-top:1px;padding-right:3px;padding-bottom:=
1px;padding-left:3px;">accountCapabilities</code>, just the top-level <c=
ode style=3D"border-top-width:1px;border-top-style:solid;border-top-colo=
r:rgb(204, 204, 204);border-right-width:1px;border-right-style:solid;bor=
der-right-color:rgb(204, 204, 204);border-bottom-width:1px;border-bottom=
-style:solid;border-bottom-color:rgb(204, 204, 204);border-left-width:1p=
x;border-left-style:solid;border-left-color:rgb(204, 204, 204);border-im=
age-outset:0;border-image-repeat:stretch;border-image-slice:100%;border-=
image-source:none;border-image-width:1;border-top-left-radius:3px;border=
-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-=
radius:3px;background-color:rgb(246, 246, 246);background-position-x:0%;=
background-position-y:0%;background-repeat:repeat;background-attachment:=
scroll;background-image:none;background-size:auto;background-origin:padd=
ing-box;background-clip:border-box;font-family:menlo, consolas, monospac=
e;font-size:90%;padding-top:1px;padding-right:3px;padding-bottom:1px;pad=
ding-left:3px;">capabilities</code>. These changes are not things within=
 a particular account; they apply at a higher level (like JMAP Core). (C=
aveat, see comment on /set below.)</div><div><i><br></i></div><div><i><b=
>=C2=A72.2.1&nbsp;The nodelist produced by JSON Path evaluation MUST be =
resolved according to the expected type of the target property</b></i></=
div><div><br></div><div>I <i>really</i> don't like this. Instead of bein=
g a pure syntactical transformation, the dispatching server must now und=
erstand the full expected structure of the method being called in order =
to apply the result reference. This is a layering violation, and could b=
e impossible for a generic JMAP proxy that doesn't understand (or need t=
o understand) the actual method calls it's dispatching to JMAP servers d=
ownstream.</div><div><br></div><div>(Yes, I saw later in =C2=A73.1 you s=
ay <i>"The type-specific resolution rules defined in this specification =
(determining whether a resolved value should be treated as a single valu=
e, an array, or a map) are applied by the JMAP method implementation lay=
er, not by the reference resolution layer."</i> =E2=80=94 that's still r=
equiring support at multiple layers.)</div><div><br></div><div>Instead, =
why not add an extra <code style=3D"border-top-width:1px;border-top-styl=
e:solid;border-top-color:rgb(204, 204, 204);border-right-width:1px;borde=
r-right-style:solid;border-right-color:rgb(204, 204, 204);border-bottom-=
width:1px;border-bottom-style:solid;border-bottom-color:rgb(204, 204, 20=
4);border-left-width:1px;border-left-style:solid;border-left-color:rgb(2=
04, 204, 204);border-image-outset:0;border-image-repeat:stretch;border-i=
mage-slice:100%;border-image-source:none;border-image-width:1;border-top=
-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:=
3px;border-bottom-left-radius:3px;background-color:rgb(246, 246, 246);ba=
ckground-position-x:0%;background-position-y:0%;background-repeat:repeat=
;background-attachment:scroll;background-image:none;background-size:auto=
;background-origin:padding-box;background-clip:border-box;font-family:me=
nlo, consolas, monospace;font-size:90%;padding-top:1px;padding-right:3px=
;padding-bottom:1px;padding-left:3px;">type</code> property to the Resul=
tReference object that gives the expected type? The caller should know w=
hat they expect this to resolve to, and that means the reference resolve=
r doesn't need to know. This lets everything be done at the Syntactic Re=
solution Phase (per =C2=A73.2).</div><div><br></div><div><i><b>=C2=A72.3=
 Usage in /set Methods</b></i></div><div><br></div><div>I think we need =
to explicitly state that should you opt in to the refplus capability you=
&nbsp;<i>cannot&nbsp;</i>set a property within a Foo object that beings =
with a literal <code style=3D"border-top-width:1px;border-top-style:soli=
d;border-top-color:rgb(204, 204, 204);border-right-width:1px;border-righ=
t-style:solid;border-right-color:rgb(204, 204, 204);border-bottom-width:=
1px;border-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);bor=
der-left-width:1px;border-left-style:solid;border-left-color:rgb(204, 20=
4, 204);border-image-outset:0;border-image-repeat:stretch;border-image-s=
lice:100%;border-image-source:none;border-image-width:1;border-top-left-=
radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;bo=
rder-bottom-left-radius:3px;background-color:rgb(246, 246, 246);backgrou=
nd-position-x:0%;background-position-y:0%;background-repeat:repeat;backg=
round-attachment:scroll;background-image:none;background-size:auto;backg=
round-origin:padding-box;background-clip:border-box;font-family:menlo, c=
onsolas, monospace;font-size:90%;padding-top:1px;padding-right:3px;paddi=
ng-bottom:1px;padding-left:3px;">#</code>. This is not a problem with an=
y of the data types being used with JMAP so far (as far as I'm aware), b=
ut worth noting for the future. (If for some reason a client&nbsp;<i>doe=
s</i>&nbsp;need to do this in the future, they must not include the refp=
lus capability in the&nbsp;<code style=3D"border-top-width:1px;border-to=
p-style:solid;border-top-color:rgb(204, 204, 204);border-right-width:1px=
;border-right-style:solid;border-right-color:rgb(204, 204, 204);border-b=
ottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204, 2=
04, 204);border-left-width:1px;border-left-style:solid;border-left-color=
:rgb(204, 204, 204);border-image-outset:0;border-image-repeat:stretch;bo=
rder-image-slice:100%;border-image-source:none;border-image-width:1;bord=
er-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-r=
adius:3px;border-bottom-left-radius:3px;background-color:rgb(246, 246, 2=
46);background-position-x:0%;background-position-y:0%;background-repeat:=
repeat;background-attachment:scroll;background-image:none;background-siz=
e:auto;background-origin:padding-box;background-clip:border-box;font-fam=
ily:menlo, consolas, monospace;font-size:90%;padding-top:1px;padding-rig=
ht:3px;padding-bottom:1px;padding-left:3px;">using</code>&nbsp;array of =
the Request object; as per RFC8620, if not explicitly opted in, the serv=
er must not apply the capability.)</div><div><br></div><div><i><b>=C2=A7=
2.3</b></i><b><i>&nbsp;If a result reference fails to resolve, the serve=
r MUST reject the creation or update of that specific object with a SetE=
rror of type "invalidResultReference"</i></b></div><div><br></div><div>T=
his is problematic, because it means the resolution has to happen at met=
hod execution time, rather than at method dispatch time. I don't think i=
t's necessary: we can resolve the references before dispatch and reject =
the whole method with <code style=3D"border-top-width:1px;border-top-sty=
le:solid;border-top-color:rgb(204, 204, 204);border-right-width:1px;bord=
er-right-style:solid;border-right-color:rgb(204, 204, 204);border-bottom=
-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204, 204, 2=
04);border-left-width:1px;border-left-style:solid;border-left-color:rgb(=
204, 204, 204);border-image-outset:0;border-image-repeat:stretch;border-=
image-slice:100%;border-image-source:none;border-image-width:1;border-to=
p-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius=
:3px;border-bottom-left-radius:3px;background-color:rgb(246, 246, 246);b=
ackground-position-x:0%;background-position-y:0%;background-repeat:repea=
t;background-attachment:scroll;background-image:none;background-size:aut=
o;background-origin:padding-box;background-clip:border-box;font-family:m=
enlo, consolas, monospace;font-size:90%;padding-top:1px;padding-right:3p=
x;padding-bottom:1px;padding-left:3px;">invalidResultReference</code> if=
 any fail. That's consistent with all the other result reference resolut=
ion, and means it can be handled in the same layer.</div><div><br></div>=
<div>Otherwise, if we really want to keep the currently specified behavi=
our, I think we will need to add the refplus capability to the&nbsp;<cod=
e style=3D"border-top-width:1px;border-top-style:solid;border-top-color:=
rgb(204, 204, 204);border-right-width:1px;border-right-style:solid;borde=
r-right-color:rgb(204, 204, 204);border-bottom-width:1px;border-bottom-s=
tyle:solid;border-bottom-color:rgb(204, 204, 204);border-left-width:1px;=
border-left-style:solid;border-left-color:rgb(204, 204, 204);border-imag=
e-outset:0;border-image-repeat:stretch;border-image-slice:100%;border-im=
age-source:none;border-image-width:1;border-top-left-radius:3px;border-t=
op-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-ra=
dius:3px;background-color:rgb(246, 246, 246);background-position-x:0%;ba=
ckground-position-y:0%;background-repeat:repeat;background-attachment:sc=
roll;background-image:none;background-size:auto;background-origin:paddin=
g-box;background-clip:border-box;font-family:menlo, consolas, monospace;=
font-size:90%;padding-top:1px;padding-right:3px;padding-bottom:1px;paddi=
ng-left:3px;">accountCapabilities</code>&nbsp;of accounts that support u=
sing ResultReferences inside <code style=3D"border-top-width:1px;border-=
top-style:solid;border-top-color:rgb(204, 204, 204);border-right-width:1=
px;border-right-style:solid;border-right-color:rgb(204, 204, 204);border=
-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,=
 204, 204);border-left-width:1px;border-left-style:solid;border-left-col=
or:rgb(204, 204, 204);border-image-outset:0;border-image-repeat:stretch;=
border-image-slice:100%;border-image-source:none;border-image-width:1;bo=
rder-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right=
-radius:3px;border-bottom-left-radius:3px;background-color:rgb(246, 246,=
 246);background-position-x:0%;background-position-y:0%;background-repea=
t:repeat;background-attachment:scroll;background-image:none;background-s=
ize:auto;background-origin:padding-box;background-clip:border-box;font-f=
amily:menlo, consolas, monospace;font-size:90%;padding-top:1px;padding-r=
ight:3px;padding-bottom:1px;padding-left:3px;">/set</code> create/update=
. Again, in the proxy case it may not be all of them.</div><div><br></di=
v><blockquote type=3D"cite" id=3D"qt" style=3D""><div><a href=3D"https:/=
/datatracker.ietf.org/doc/draft-ietf-jmap-metadata/">https://datatracker=
.ietf.org/doc/draft-ietf-jmap-metadata/</a></div></blockquote><div><br><=
/div><div>I think this is looking fairly solid. A few comments:</div><di=
v><br></div><div><b><i>=C2=A72.1.2 Servers SHOULD document whether they =
provide read-only or read-write access to ImapMetadata.</i></b></div><di=
v><b><i>=C2=A72.1.3&nbsp;</i><i>Servers SHOULD document whether they pro=
vide read-only or read-write access to WebDavMetadata.</i><i></i></b><br=
></div><div><br></div><div>Why not put this in the capabilities?</div><d=
iv><br></div><div><b><i>=C2=A7</i></b><b>3.1 "alreadyExists" SetError [=E2=
=80=A6] MAY include an "existingId" property containing the id of the ex=
isting Metadata object.</b></div><div><br></div><div>I'd change this MAY=
 to a MUST =E2=80=94 it's easy to implement, and if it's only a MAY a cl=
ient can't rely on it, which is a pain. (As a general rule,&nbsp;</div><=
div><br></div><div><b><i>=C2=A74.1&nbsp;The response to an extended /get=
 method includes the following additional property</i></b><br></div><div=
><br></div><div>I think we probably need to include <code style=3D"borde=
r-top-width:1px;border-top-style:solid;border-top-color:rgb(204, 204, 20=
4);border-right-width:1px;border-right-style:solid;border-right-color:rg=
b(204, 204, 204);border-bottom-width:1px;border-bottom-style:solid;borde=
r-bottom-color:rgb(204, 204, 204);border-left-width:1px;border-left-styl=
e:solid;border-left-color:rgb(204, 204, 204);border-image-outset:0;borde=
r-image-repeat:stretch;border-image-slice:100%;border-image-source:none;=
border-image-width:1;border-top-left-radius:3px;border-top-right-radius:=
3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;backgro=
und-color:rgb(246, 246, 246);background-position-x:0%;background-positio=
n-y:0%;background-repeat:repeat;background-attachment:scroll;background-=
image:none;background-size:auto;background-origin:padding-box;background=
-clip:border-box;font-family:menlo, consolas, monospace;font-size:90%;pa=
dding-top:1px;padding-right:3px;padding-bottom:1px;padding-left:3px;">me=
tadataState</code> in the response as well?</div><div><i><b><br></b></i>=
</div><div><i><b>=C2=A74.2.1&nbsp;Servers SHOULD NOT generate [=E2=80=A6=
] state changes for automatically deleted metadata. The deletion is cons=
idered an implicit consequence of destroying the related object. However=
, servers MAY emit push notifications or update metadata state strings t=
o reflect that metadata has been deleted, if such notifications would ot=
herwise occur for explicitly deleted metadata.</b></i><br></div><div><br=
></div><div>I'm not quite sure what you're going for here. Surely the me=
tadata state&nbsp;<i>has</i>&nbsp;to change if a metadata object is dest=
royed, regardless of how this happened. Otherwise, the <code style=3D"bo=
rder-top-width:1px;border-top-style:solid;border-top-color:rgb(204, 204,=
 204);border-right-width:1px;border-right-style:solid;border-right-color=
:rgb(204, 204, 204);border-bottom-width:1px;border-bottom-style:solid;bo=
rder-bottom-color:rgb(204, 204, 204);border-left-width:1px;border-left-s=
tyle:solid;border-left-color:rgb(204, 204, 204);border-image-outset:0;bo=
rder-image-repeat:stretch;border-image-slice:100%;border-image-source:no=
ne;border-image-width:1;border-top-left-radius:3px;border-top-right-radi=
us:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;back=
ground-color:rgb(246, 246, 246);background-position-x:0%;background-posi=
tion-y:0%;background-repeat:repeat;background-attachment:scroll;backgrou=
nd-image:none;background-size:auto;background-origin:padding-box;backgro=
und-clip:border-box;font-family:menlo, consolas, monospace;font-size:90%=
;padding-top:1px;padding-right:3px;padding-bottom:1px;padding-left:3px;"=
>/changes</code>&nbsp;updates won't work correctly.</div><div><br></div>=
<div>Related, the document doesn't currently specify that changes purely=
 to a Metadata object SHOULD NOT change the state string for the related=
 type, but I think that's the idea. Although=E2=80=A6</div><div><br></di=
v><div><b>Is this the right approach?</b></div><div><br></div><div>With =
my client implementer hat on, I was thinking about how I would want to u=
se metadata. Generally, I'd want to be able to say "I'm interested in me=
tadata for this particular type" and then fetch/update it with the insta=
nces of that type themselves. I can't think of a circumstance where I'd =
want metadata without the related object, but I could definitely just ha=
ve a small subset of the dataset for a particular object (e.g. I have lo=
aded 100 emails for a user with 1,000,000 messages). The current approac=
h is a bit painful:</div><ul><li>I can fetch the metadata with the Email=
 objects by using the <i>fetchMetadata</i>&nbsp;argument. Fine.</li><li>=
The Metadata state changes. I call <code style=3D"border-top-width:1px;b=
order-top-style:solid;border-top-color:rgb(204, 204, 204);border-right-w=
idth:1px;border-right-style:solid;border-right-color:rgb(204, 204, 204);=
border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rg=
b(204, 204, 204);border-left-width:1px;border-left-style:solid;border-le=
ft-color:rgb(204, 204, 204);border-image-outset:0;border-image-repeat:st=
retch;border-image-slice:100%;border-image-source:none;border-image-widt=
h:1;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom=
-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(246=
, 246, 246);background-position-x:0%;background-position-y:0%;background=
-repeat:repeat;background-attachment:scroll;background-image:none;backgr=
ound-size:auto;background-origin:padding-box;background-clip:border-box;=
font-family:menlo, consolas, monospace;font-size:90%;padding-top:1px;pad=
ding-right:3px;padding-bottom:1px;padding-left:3px;">Metadata/changes</c=
ode> with&nbsp;<i>filterRelatedType</i> set to <code style=3D"border-top=
-width:1px;border-top-style:solid;border-top-color:rgb(204, 204, 204);bo=
rder-right-width:1px;border-right-style:solid;border-right-color:rgb(204=
, 204, 204);border-bottom-width:1px;border-bottom-style:solid;border-bot=
tom-color:rgb(204, 204, 204);border-left-width:1px;border-left-style:sol=
id;border-left-color:rgb(204, 204, 204);border-image-outset:0;border-ima=
ge-repeat:stretch;border-image-slice:100%;border-image-source:none;borde=
r-image-width:1;border-top-left-radius:3px;border-top-right-radius:3px;b=
order-bottom-right-radius:3px;border-bottom-left-radius:3px;background-c=
olor:rgb(246, 246, 246);background-position-x:0%;background-position-y:0=
%;background-repeat:repeat;background-attachment:scroll;background-image=
:none;background-size:auto;background-origin:padding-box;background-clip=
:border-box;font-family:menlo, consolas, monospace;font-size:90%;padding=
-top:1px;padding-right:3px;padding-bottom:1px;padding-left:3px;">"Email"=
</code>. I can ignore any <i>updated</i>&nbsp;metadata objects I don't h=
ave, but I have to always fetch the <i>created</i> metadata objects, as =
I have no way of knowing if they're related to the Email objects I curre=
ntly have in memory or not.<br></li><li>I can't search for a Foo object =
that has some particular metadata AND a regular property (e.g. if I used=
 metadata to store a <a href=3D"https://www.fastmail.com/features/memos/=
">memo</a>&nbsp;on an Email, and wanted to search for all emails that ar=
e in the inbox and have a memo with the text "foo").</li></ul><div>A ver=
y different approach would be:</div><ul><li>Data types with metadata sup=
port (as per the capabilities) get a mutable <code style=3D"border-top-w=
idth:1px;border-top-style:solid;border-top-color:rgb(204, 204, 204);bord=
er-right-width:1px;border-right-style:solid;border-right-color:rgb(204, =
204, 204);border-bottom-width:1px;border-bottom-style:solid;border-botto=
m-color:rgb(204, 204, 204);border-left-width:1px;border-left-style:solid=
;border-left-color:rgb(204, 204, 204);border-image-outset:0;border-image=
-repeat:stretch;border-image-slice:100%;border-image-source:none;border-=
image-width:1;border-top-left-radius:3px;border-top-right-radius:3px;bor=
der-bottom-right-radius:3px;border-bottom-left-radius:3px;background-col=
or:rgb(246, 246, 246);background-position-x:0%;background-position-y:0%;=
background-repeat:repeat;background-attachment:scroll;background-image:n=
one;background-size:auto;background-origin:padding-box;background-clip:b=
order-box;font-family:menlo, consolas, monospace;font-size:90%;padding-t=
op:1px;padding-right:3px;padding-bottom:1px;padding-left:3px;">_metadata=
_: String[*]</code>&nbsp;property if you opt in to the capability. We co=
uld have a <code style=3D"border-top-width:1px;border-top-style:solid;bo=
rder-top-color:rgb(204, 204, 204);border-right-width:1px;border-right-st=
yle:solid;border-right-color:rgb(204, 204, 204);border-bottom-width:1px;=
border-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);border-=
left-width:1px;border-left-style:solid;border-left-color:rgb(204, 204, 2=
04);border-image-outset:0;border-image-repeat:stretch;border-image-slice=
:100%;border-image-source:none;border-image-width:1;border-top-left-radi=
us:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border=
-bottom-left-radius:3px;background-color:rgb(246, 246, 246);background-p=
osition-x:0%;background-position-y:0%;background-repeat:repeat;backgroun=
d-attachment:scroll;background-image:none;background-size:auto;backgroun=
d-origin:padding-box;background-clip:border-box;font-family:menlo, conso=
las, monospace;font-size:90%;padding-top:1px;padding-right:3px;padding-b=
ottom:1px;padding-left:3px;">_private_metadata_</code> property too for =
private metadata, if supported (per the capability).&nbsp;</li><li>The v=
alue of this property is a (possibly empty) object (never null so you ca=
n always patch). The keys at the top level are registered, or a domain n=
ame:</li><ul><li><code style=3D"border-top-width:1px;border-top-style:so=
lid;border-top-color:rgb(204, 204, 204);border-right-width:1px;border-ri=
ght-style:solid;border-right-color:rgb(204, 204, 204);border-bottom-widt=
h:1px;border-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204, =
204, 204);border-image-outset:0;border-image-repeat:stretch;border-image=
-slice:100%;border-image-source:none;border-image-width:1;border-top-lef=
t-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;=
border-bottom-left-radius:3px;background-color:rgb(246, 246, 246);backgr=
ound-position-x:0%;background-position-y:0%;background-repeat:repeat;bac=
kground-attachment:scroll;background-image:none;background-size:auto;bac=
kground-origin:padding-box;background-clip:border-box;font-family:menlo,=
 consolas, monospace;font-size:90%;padding-top:1px;padding-right:3px;pad=
ding-bottom:1px;padding-left:3px;">imap</code>: maps to IMAP metadata</l=
i><li><code style=3D"border-top-width:1px;border-top-style:solid;border-=
top-color:rgb(204, 204, 204);border-right-width:1px;border-right-style:s=
olid;border-right-color:rgb(204, 204, 204);border-bottom-width:1px;borde=
r-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);border-left-=
width:1px;border-left-style:solid;border-left-color:rgb(204, 204, 204);b=
order-image-outset:0;border-image-repeat:stretch;border-image-slice:100%=
;border-image-source:none;border-image-width:1;border-top-left-radius:3p=
x;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bott=
om-left-radius:3px;background-color:rgb(246, 246, 246);background-positi=
on-x:0%;background-position-y:0%;background-repeat:repeat;background-att=
achment:scroll;background-image:none;background-size:auto;background-ori=
gin:padding-box;background-clip:border-box;font-family:menlo, consolas, =
monospace;font-size:90%;padding-top:1px;padding-right:3px;padding-bottom=
:1px;padding-left:3px;">webdav</code>: maps to WebDAV metadata</li><li><=
code style=3D"border-top-width:1px;border-top-style:solid;border-top-col=
or:rgb(204, 204, 204);border-right-width:1px;border-right-style:solid;bo=
rder-right-color:rgb(204, 204, 204);border-bottom-width:1px;border-botto=
m-style:solid;border-bottom-color:rgb(204, 204, 204);border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204, 204, 204);border-i=
mage-outset:0;border-image-repeat:stretch;border-image-slice:100%;border=
-image-source:none;border-image-width:1;border-top-left-radius:3px;borde=
r-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left=
-radius:3px;background-color:rgb(246, 246, 246);background-position-x:0%=
;background-position-y:0%;background-repeat:repeat;background-attachment=
:scroll;background-image:none;background-size:auto;background-origin:pad=
ding-box;background-clip:border-box;font-family:menlo, consolas, monospa=
ce;font-size:90%;padding-top:1px;padding-right:3px;padding-bottom:1px;pa=
dding-left:3px;">example.com</code>: maps to arbitrary vendor data.</li>=
</ul><li>The metadata property can be specified in the <i>properties</i>=
 argument to <code style=3D"border-top-width:1px;border-top-style:solid;=
border-top-color:rgb(204, 204, 204);border-right-width:1px;border-right-=
style:solid;border-right-color:rgb(204, 204, 204);border-bottom-width:1p=
x;border-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);borde=
r-left-width:1px;border-left-style:solid;border-left-color:rgb(204, 204,=
 204);border-image-outset:0;border-image-repeat:stretch;border-image-sli=
ce:100%;border-image-source:none;border-image-width:1;border-top-left-ra=
dius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;bord=
er-bottom-left-radius:3px;background-color:rgb(246, 246, 246);background=
-position-x:0%;background-position-y:0%;background-repeat:repeat;backgro=
und-attachment:scroll;background-image:none;background-size:auto;backgro=
und-origin:padding-box;background-clip:border-box;font-family:menlo, con=
solas, monospace;font-size:90%;padding-top:1px;padding-right:3px;padding=
-bottom:1px;padding-left:3px;">Foo/get</code>, like any other property. =
If you don't specify any properties, it will be returned with the defaul=
t set of properties (normally everything) for that data type. (Or maybe =
we'd need a way to say "give me all the default properties, but <i>not</=
i>&nbsp;the metadata properties for this object type"?)</li><li><code st=
yle=3D"border-top-width:1px;border-top-style:solid;border-top-color:rgb(=
204, 204, 204);border-right-width:1px;border-right-style:solid;border-ri=
ght-color:rgb(204, 204, 204);border-bottom-width:1px;border-bottom-style=
:solid;border-bottom-color:rgb(204, 204, 204);border-left-width:1px;bord=
er-left-style:solid;border-left-color:rgb(204, 204, 204);border-image-ou=
tset:0;border-image-repeat:stretch;border-image-slice:100%;border-image-=
source:none;border-image-width:1;border-top-left-radius:3px;border-top-r=
ight-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius=
:3px;background-color:rgb(246, 246, 246);background-position-x:0%;backgr=
ound-position-y:0%;background-repeat:repeat;background-attachment:scroll=
;background-image:none;background-size:auto;background-origin:padding-bo=
x;background-clip:border-box;font-family:menlo, consolas, monospace;font=
-size:90%;padding-top:1px;padding-right:3px;padding-bottom:1px;padding-l=
eft:3px;">Foo/changes</code> returns objects where the <code style=3D"bo=
rder-top-width:1px;border-top-style:solid;border-top-color:rgb(204, 204,=
 204);border-right-width:1px;border-right-style:solid;border-right-color=
:rgb(204, 204, 204);border-bottom-width:1px;border-bottom-style:solid;bo=
rder-bottom-color:rgb(204, 204, 204);border-left-width:1px;border-left-s=
tyle:solid;border-left-color:rgb(204, 204, 204);border-image-outset:0;bo=
rder-image-repeat:stretch;border-image-slice:100%;border-image-source:no=
ne;border-image-width:1;border-top-left-radius:3px;border-top-right-radi=
us:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;back=
ground-color:rgb(246, 246, 246);background-position-x:0%;background-posi=
tion-y:0%;background-repeat:repeat;background-attachment:scroll;backgrou=
nd-image:none;background-size:auto;background-origin:padding-box;backgro=
und-clip:border-box;font-family:menlo, consolas, monospace;font-size:90%=
;padding-top:1px;padding-right:3px;padding-bottom:1px;padding-left:3px;"=
>_metadata_</code> property has changed in the <i>updated</i>&nbsp;argum=
ent of the response. We add an <i>updatedProperties</i> argument to the =
response, <a href=3D"https://www.rfc-editor.org/rfc/rfc8621.html#section=
-2.2">like in Mailbox/changes</a>. If only metadata has changed, the ser=
ver should use this to indicate that, so you can then only fetch the met=
adata property. Possibly we add an extra argument to <code style=3D"bord=
er-top-width:1px;border-top-style:solid;border-top-color:rgb(204, 204, 2=
04);border-right-width:1px;border-right-style:solid;border-right-color:r=
gb(204, 204, 204);border-bottom-width:1px;border-bottom-style:solid;bord=
er-bottom-color:rgb(204, 204, 204);border-left-width:1px;border-left-sty=
le:solid;border-left-color:rgb(204, 204, 204);border-image-outset:0;bord=
er-image-repeat:stretch;border-image-slice:100%;border-image-source:none=
;border-image-width:1;border-top-left-radius:3px;border-top-right-radius=
:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;backgr=
ound-color:rgb(246, 246, 246);background-position-x:0%;background-positi=
on-y:0%;background-repeat:repeat;background-attachment:scroll;background=
-image:none;background-size:auto;background-origin:padding-box;backgroun=
d-clip:border-box;font-family:menlo, consolas, monospace;font-size:90%;p=
adding-top:1px;padding-right:3px;padding-bottom:1px;padding-left:3px;">F=
oo/changes</code> to ignore metadata-only changes for data types where y=
ou're not interested in the metadata.</li><li>We define some extensions =
to the&nbsp;<code style=3D"border-top-width:1px;border-top-style:solid;b=
order-top-color:rgb(204, 204, 204);border-right-width:1px;border-right-s=
tyle:solid;border-right-color:rgb(204, 204, 204);border-bottom-width:1px=
;border-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);border=
-left-width:1px;border-left-style:solid;border-left-color:rgb(204, 204, =
204);border-image-outset:0;border-image-repeat:stretch;border-image-slic=
e:100%;border-image-source:none;border-image-width:1;border-top-left-rad=
ius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;borde=
r-bottom-left-radius:3px;background-color:rgb(246, 246, 246);background-=
position-x:0%;background-position-y:0%;background-repeat:repeat;backgrou=
nd-attachment:scroll;background-image:none;background-size:auto;backgrou=
nd-origin:padding-box;background-clip:border-box;font-family:menlo, cons=
olas, monospace;font-size:90%;padding-top:1px;padding-right:3px;padding-=
bottom:1px;padding-left:3px;">Foo/query</code>&nbsp;FilterCondition for =
any data type that supports metadata:</li><ul><li>the presence of metada=
ta at a particular path, e.g., <code style=3D"border-top-width:1px;borde=
r-top-style:solid;border-top-color:rgb(204, 204, 204);border-right-width=
:1px;border-right-style:solid;border-right-color:rgb(204, 204, 204);bord=
er-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(20=
4, 204, 204);border-left-width:1px;border-left-style:solid;border-left-c=
olor:rgb(204, 204, 204);border-image-outset:0;border-image-repeat:stretc=
h;border-image-slice:100%;border-image-source:none;border-image-width:1;=
border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-rig=
ht-radius:3px;border-bottom-left-radius:3px;background-color:rgb(246, 24=
6, 246);background-position-x:0%;background-position-y:0%;background-rep=
eat:repeat;background-attachment:scroll;background-image:none;background=
-size:auto;background-origin:padding-box;background-clip:border-box;font=
-family:menlo, consolas, monospace;font-size:90%;padding-top:1px;padding=
-right:3px;padding-bottom:1px;padding-left:3px;">{"metadataExists": "fas=
tmail.com/memo"}</code> =E2=80=94 this matches any object where it has a=
 value defined at that path.</li><li>text match at a particular path. e.=
g.,&nbsp;<code style=3D"border-top-width:1px;border-top-style:solid;bord=
er-top-color:rgb(204, 204, 204);border-right-width:1px;border-right-styl=
e:solid;border-right-color:rgb(204, 204, 204);border-bottom-width:1px;bo=
rder-bottom-style:solid;border-bottom-color:rgb(204, 204, 204);border-le=
ft-width:1px;border-left-style:solid;border-left-color:rgb(204, 204, 204=
);border-image-outset:0;border-image-repeat:stretch;border-image-slice:1=
00%;border-image-source:none;border-image-width:1;border-top-left-radius=
:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-b=
ottom-left-radius:3px;background-color:rgb(246, 246, 246);background-pos=
ition-x:0%;background-position-y:0%;background-repeat:repeat;background-=
attachment:scroll;background-image:none;background-size:auto;background-=
origin:padding-box;background-clip:border-box;font-family:menlo, consola=
s, monospace;font-size:90%;padding-top:1px;padding-right:3px;padding-bot=
tom:1px;padding-left:3px;">{"metadataText": { path: "fastmail.com/memo",=
 value: "foo"}</code>&nbsp;=E2=80=94 looks for a string in the property =
at a particular path. Is false if the path doesn't exist or isn't a stri=
ng type.</li></ul><li>That's =E2=80=A6 kind of it? You can use standard =
<code style=3D"border-top-width:1px;border-top-style:solid;border-top-co=
lor:rgb(204, 204, 204);border-right-width:1px;border-right-style:solid;b=
order-right-color:rgb(204, 204, 204);border-bottom-width:1px;border-bott=
om-style:solid;border-bottom-color:rgb(204, 204, 204);border-left-width:=
1px;border-left-style:solid;border-left-color:rgb(204, 204, 204);border-=
image-outset:0;border-image-repeat:stretch;border-image-slice:100%;borde=
r-image-source:none;border-image-width:1;border-top-left-radius:3px;bord=
er-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-lef=
t-radius:3px;background-color:rgb(246, 246, 246);background-position-x:0=
%;background-position-y:0%;background-repeat:repeat;background-attachmen=
t:scroll;background-image:none;background-size:auto;background-origin:pa=
dding-box;background-clip:border-box;font-family:menlo, consolas, monosp=
ace;font-size:90%;padding-top:1px;padding-right:3px;padding-bottom:1px;p=
adding-left:3px;">Foo/set</code> patching to update specific metadata pr=
operties without stomping on other vendors=E2=80=99 metadata. You always=
 keep your metadata in sync with the underlying objects. You don't reall=
y need to change any code in the client, and all existing sync code will=
 just work.</li></ul><div>Thoughts? This seems both simpler and more fun=
ctional to me, and I don't see any obvious drawbacks at first glance.</d=
iv><div><br></div><div>Cheers,</div><div id=3D"sig64588216"><div class=3D=
"signature">Neil.<br></div></div></body></html>
--6a26f77ea7d22c06368dfcfd8932afc2156f1737--

