Return-Path: <mauro@stalw.art>
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 03207F624D9C
	for <jmap@mail2.ietf.org>; Wed, 27 May 2026 11:47:21 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ietf.org; s=ietf1;
	t=1779907641; bh=doBcGHhUdLbvPAuHvLjdIG2lgahiPXmMp4ih7nNuV3o=;
	h=From:Subject:Date:References:To:In-Reply-To;
	b=GbsUpzqRQeKAvdET3KqkHMr2dZn4pgGj+nAk5hIaOg990HCuQBujBrdKb61vQx39L
	 Uhbb1uPywkZbPwXY+H68vHhyvriTA9k2gTf1xc1jo2vxL5Dmw6RLDh4XYUvb0ExL2b
	 K2MPZS7vwYqb5nj9mllbzwVB1/2Da2nNET/AmwCk=
X-Virus-Scanned: amavisd-new at ietf.org
X-Spam-Flag: NO
X-Spam-Score: -2.099
X-Spam-Level: 
X-Spam-Status: No, score=-2.099 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,
	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=neutral
	reason="invalid (unsupported algorithm ed25519-sha256)"
	header.d=stalw.art header.b="vWSGUFUg"; dkim=pass (2048-bit key)
	header.d=stalw.art header.b="Njh+UDaP"
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 YdKUdPk9BlmU for <jmap@mail2.ietf.org>;
	Wed, 27 May 2026 11:47:19 -0700 (PDT)
Received: from mail.stalw.art (mail.stalw.art [135.181.195.209])
	(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 2F052F624D8E
	for <jmap@ietf.org>; Wed, 27 May 2026 11:47:19 -0700 (PDT)
DKIM-Signature: v=1; a=ed25519-sha256; s=v1-ed25519-20260418; d=stalw.art;
 c=relaxed/relaxed; r=y;
	h=Message-Id:To:Date:Subject:From; t=1779907637; bh=nG2m2CYvWvz7aKckwfwbe/i
	EYGWDnVv/0n5PpWwfOuw=; b=vWSGUFUg6hR1/YAFdwIFaULpSpxQYJHYkAKVE0jSPw3jo+qwi1
	9ghAfAz6qYFeokZ9zkZDT9pz++UZaRwxpVDA==;
DKIM-Signature: v=1; a=rsa-sha256; s=v1-rsa-20260418; d=stalw.art;
 c=relaxed/relaxed; r=y;
	h=Message-Id:To:Date:Subject:From; t=1779907637; bh=nG2m2CYvWvz7aKckwfwbe/i
	EYGWDnVv/0n5PpWwfOuw=; b=Njh+UDaPX3i6+4xRQdRchi3Pnc88nJoztwCHBmugoKdd9ePfxl
	zvlAQXcnG1orklCqyOBBlGaINTfq9//87pyTZXAqZK+DdeyGH32KG3fgjTnn9RMVnpygMZP7AbI
	yOssGw+Rx+PyeUi4Yts1rNn64mkxnWaiFgeF/g9fSKmUr22P5DDeW45RpWbH03GyrtX7RUtczCf
	t9CGraRVHPlVrDRxQcY9Ru2N++ulvazl4Gz3BVxq+6bUqqM0gRJhLg+ekHqjErvJldTuAD+z+u5
	n/PHbCqioJL/lffnzvTVjJ80bx9uBrqIDxFSSfVgnuuFesmxc+LzMBzg5wi5f7x5AqA==;
From: Mauro De Gennaro <mauro@stalw.art>
Content-Type: text/plain;
	charset=utf-8
Content-Transfer-Encoding: quoted-printable
Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.500.181\))
Date: Wed, 27 May 2026 20:47:07 +0200
References: <8397988B-24C5-42D7-BD1E-45CEDD009AC5@stalw.art>
 <9e8b403c-e0d3-4af6-ac47-c1af06f27e1e@dogfoodapp.fastmail.com>
To: JMAP IETF <jmap@ietf.org>
In-Reply-To: <9e8b403c-e0d3-4af6-ac47-c1af06f27e1e@dogfoodapp.fastmail.com>
Message-Id: <727134A4-1BA7-4F25-AAD8-307F8DDB6BAC@stalw.art>
X-Mailer: Apple Mail (2.3864.500.181)
Message-ID-Hash: 2EYAKS7T56ZSVIG54ZK4VIWQGECH323L
X-Message-ID-Hash: 2EYAKS7T56ZSVIG54ZK4VIWQGECH323L
X-MailFrom: mauro@stalw.art
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/b9onajuGvYW1P8ZDyWxtXAXR__Q>
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>

Hi Neil,

Thank you for reviewing all three drafts and apologies for taking over a =
month to reply, much longer than I'd intended.

On the three drafts:

- JMAP Mail Sharing: I've just bumped it to -01 to keep it alive (the =
-00 was about to expire), but I haven't added anything new. Happy to =
take it to WG last call if the everyone agrees.

- JMAP refplus: We can discuss this in Vienna if you like. On the =
use-case question, while implementing a JMAP CLI and a JMAP web UI I =
came across cases where refplus would be quite helpful. However, I agree =
that if I'm the only one with a real use case, that's not enough to =
justify standardisation. I'd like to ask around in Vienna and see if =
others are interested before pushing further; if there's no general =
interest for it, I'm fine to drop it.

- JMAP Metadata: I've taken all your suggestions on board and just =
published -02. The biggest change is the move to the property-on-object =
design you proposed. The separate Metadata data type and its methods are =
gone. I also ended up dropping the imap and webdav bridge namespaces, =
leaving them for future extensions if metadata bridging is ever needed.


Best,
Mauro



> On 15 Apr 2026, at 06:50, Neil Jenkins =
<neilj=3D40fastmailteam.com@dmarc.ietf.org> wrote:
>=20
> I've read through all of these again.
>=20
>> https://datatracker.ietf.org/doc/draft-ietf-jmap-mail-sharing/
>=20
> This looks great, I think it should go to WG last call and be =
submitted for publication.
>=20
>> https://datatracker.ietf.org/doc/draft-ietf-jmap-refplus/
>=20
> My overall view of this is still that the added complexity (and =
execution performance concerns) of this outweighs the performance =
benefits of reducing 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:
>=20
> =C2=A71.2.1. The value of this property in the JMAP Session =
"accountCapabilities" property is an empty object.
>=20
> 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). (Caveat, see comment on /set below.)
>=20
> =C2=A72.2.1 The nodelist produced by JSON Path evaluation MUST be =
resolved according to the expected type of the target property
>=20
> I really don't like this. Instead of being a pure syntactical =
transformation, the dispatching server must now understand the full =
expected structure of the method being called in order to apply the =
result reference. This is a layering violation, and could be impossible =
for a generic JMAP proxy that doesn't understand (or need to understand) =
the actual method calls it's dispatching to JMAP servers downstream.
>=20
> (Yes, I saw later in =C2=A73.1 you say "The type-specific resolution =
rules 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 layer." =E2=80=94 that's still requiring support at multiple =
layers.)
>=20
> Instead, why not add an extra type property to the ResultReference =
object that gives the expected type? The caller should know what they =
expect 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).
>=20
> =C2=A72.3 Usage in /set Methods
>=20
> I think we need to explicitly state that should you opt in to the =
refplus 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 being used with JMAP so far (as far as I'm aware), but worth =
noting for the future. (If for some reason a client does need to do this =
in the future, they must not include the refplus capability in the using =
array of the Request object; as per RFC8620, if not explicitly opted in, =
the server must not apply the capability.)
>=20
> =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"
>=20
> This is problematic, because it means the resolution has to happen at =
method 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 =
consistent with all the other result reference resolution, and means it =
can be handled in the same layer.
>=20
> Otherwise, if we really want to keep the currently specified =
behaviour, I think we will need to add the refplus capability to the =
accountCapabilities of accounts that support using ResultReferences =
inside /set create/update. Again, in the proxy case it may not be all of =
them.
>=20
>> https://datatracker.ietf.org/doc/draft-ietf-jmap-metadata/
>=20
>=20
> I think this is looking fairly solid. A few comments:
>=20
> =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 or =
read-write access to WebDavMetadata.
>=20
> Why not put this in the capabilities?
>=20
> =C2=A73.1 "alreadyExists" SetError [=E2=80=A6] MAY include an =
"existingId" property containing the id of the existing Metadata object.
>=20
> I'd change this MAY to a MUST =E2=80=94 it's easy to implement, and if =
it's only a MAY a client can't rely on it, which is a pain. (As a =
general rule,=20
>=20
> =C2=A74.1 The response to an extended /get method includes the =
following additional property
>=20
> I think we probably need to include metadataState in the response as =
well?
>=20
> =C2=A74.2.1 Servers SHOULD NOT generate [=E2=80=A6] state changes for =
automatically deleted metadata. The deletion is considered an implicit =
consequence of destroying the related object. However, servers MAY emit =
push notifications or update metadata state strings to reflect that =
metadata has been deleted, if such notifications would otherwise occur =
for explicitly deleted metadata.
>=20
> 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 =
this happened. Otherwise, the /changes updates won't work correctly.
>=20
> 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
>=20
> Is this the right approach?
>=20
> 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 just have a small subset of the dataset for a =
particular object (e.g. I have loaded 100 emails for a user with =
1,000,000 messages). The current approach 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 =
filterRelatedType 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 =
objects I currently have in memory or not.
>     =E2=80=A2 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 memo =
on an Email, and wanted to search for all emails that are in the inbox =
and have a memo with the text "foo").
> A very different approach would be:
>     =E2=80=A2 Data types with metadata support (as per the =
capabilities) get a mutable _metadata_: String[*] property if you opt in =
to the capability. We could have a _private_metadata_ property too for =
private metadata, if supported (per the capability).=20
>     =E2=80=A2 The value of this property is a (possibly empty) object =
(never null so you can always patch). The keys at the top level are =
registered, 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 =
argument to Foo/get, like any other property. If you don't specify any =
properties, it will be returned with the default 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 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 =
updatedProperties argument to the response, like in Mailbox/changes. If =
only metadata has changed, the server should use this to indicate that, =
so you can then only fetch the metadata property. Possibly we add an =
extra argument to Foo/changes to ignore metadata-only changes for data =
types where you're not 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., =
{"metadataExists": "fastmail.com/memo"} =E2=80=94 this matches any =
object where 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 in 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 patching to update specific metadata properties without stomping =
on other vendors=E2=80=99 metadata. You always keep your metadata in =
sync with the underlying objects. You don't really need to change any =
code in the client, 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.
>=20
> Cheers,
> Neil.
> _______________________________________________
> JMAP mailing list -- jmap@ietf.org
> To unsubscribe send an email to jmap-leave@ietf.org

