[JMAP] Re: JMAP for Calendars comments

Neil Jenkins <neilj@fastmailteam.com> Fri, 24 October 2025 04:25 UTC

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 61E4F7B75E07 for <jmap@mail2.ietf.org>; Thu, 23 Oct 2025 21:25:15 -0700 (PDT)
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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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="I3QpMV17"; dkim=pass (2048-bit key) header.d=messagingengine.com header.b="In+c9xeV"
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 olZJm0EXEYmV for <jmap@mail2.ietf.org>; Thu, 23 Oct 2025 21:25:14 -0700 (PDT)
Received: from fhigh-b5-smtp.messagingengine.com (fhigh-b5-smtp.messagingengine.com [202.12.124.156]) (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 A38CA7B75D46 for <jmap@ietf.org>; Thu, 23 Oct 2025 21:24:42 -0700 (PDT)
Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfhigh.stl.internal (Postfix) with ESMTP id 9989B7A012C for <jmap@ietf.org>; Fri, 24 Oct 2025 00:24:36 -0400 (EDT)
Received: from phl-imap-15 ([10.202.2.104]) by phl-compute-02.internal (MEProxy); Fri, 24 Oct 2025 00:24:36 -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=1761279876; x= 1761366276; bh=WSbzSB2CMr1EqOUTiEDeR0reqbCXBcaqpcMksFhT+fI=; b=I 3QpMV17cDqCw3wanq7iIPeaJKEruBnklaWy7Sf4GuqDeivE2npDIdKTd5P6VBqKE eQIiZLfwIz/nDhSZuvQ0It/o3qfVfvjZdWriaR3R/0yTnhwKwpzmzT8OeupGu5FE TfFBc7QkPO0aWLugmp/SzPpKq4oYS85t97Bwp57qZGCNkyVVMrkI5VP3E/UeK1w4 Ib0a7fdvfdAThI29pcLuMOtyn5RifCXW+8ll5/WnFVd7yxFy8qnprNxxBOKgykpX HjdquUjKJ1nAD3jLTjCzUj4+g+ZkzQJmhby0cGFYugoUqaIQqPL5fiiKDpG1xyZC SNuNZS6JsL8i1lnOEctNQ==
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= 1761279876; x=1761366276; bh=WSbzSB2CMr1EqOUTiEDeR0reqbCXBcaqpcM ksFhT+fI=; b=In+c9xeVzRp4VcljjQMgJYuqReoLOnDWYM3WKQtBuMOv4ULIWkK N9wxiK8ut48T4wvMyVU+V8AlZUXgYDKdkRtBkGQDS/Ta5DEyffkhT6mDer1fuX1d 6MFNNDMcBRLQjhDFQFtdzzVw8s8b1V7Nvbo8fvqEQaPB9UuMopm0ITEXpp+g3fdI NZQftQ/Q8CnEGAow4d0lBMmmhe2+Fi3H6RLYdDUgc3FJERLP8yTpMB2E53Sz5kLR XOE28Th+XDPXgLMS4J3BcD4WIVs9bmoY6FTAxoKopIhxgQwSD0n+I0E+fLIYrYTL 5mos+V5wHdkOR08rhcf7eoVPgoKluLnJbqg==
X-ME-Sender: <xms:hP_6aB2oHoa5cKbFqrCypHiYzNFLovWRZkTIE5Svz0e4KP2Zs0ttMA> <xme:hP_6aC52YqJGpWl4wMqXyTZn1YLTFl-u4S7exMMDTn5qnZgI962OU6-wGA99gXTpx 3EzVV5UkI8cSTc0QftrHXXIe9roZjzYBCxW4gtzNVgTpVTQiQ>
X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggddugeekfeejucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepofggfffhvffkjghfufgtsegrtderreertdejnecuhfhrohhmpedfpfgvihhlucfl vghnkhhinhhsfdcuoehnvghilhhjsehfrghsthhmrghilhhtvggrmhdrtghomheqnecugg ftrfgrthhtvghrnhepveevteevueelvdfhvefggfdtledvveetleekfeeileeikedutedt leegueekveegnecuffhomhgrihhnpehrfhgtqdgvughithhorhdrohhrghenucevlhhush htvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehnvghilhhjsehfrghs thhmrghilhhtvggrmhdrtghomhdpnhgspghrtghpthhtohepuddpmhhouggvpehsmhhtph houhhtpdhrtghpthhtohepjhhmrghpsehivghtfhdrohhrgh
X-ME-Proxy: <xmx:hP_6aNZ57I-uxsClt6YMwxoyhqHaiB0-mKT9IECq-4kygUjUYyqGbw> <xmx:hP_6aLU4DkkhMMKtjlEFLdoo5N01pKzODiyBDOvru6-aKGMvSrDLbQ> <xmx:hP_6aFku_5opPGOt7YIwpBzK4eik0udpp2HzJpDQNBpVjoPcty9Qww> <xmx:hP_6aAwzzJIYykglq-S3xLah1CzjzZpZeDDcH_u_Z41YN3memAHGCg> <xmx:hP_6aMwTZB_d3xAsYGaGecvGHVtSQvauUs32rTCEcgZYy1FPEHFqCkk->
Feedback-ID: ibc614277:Fastmail
Received: by mailuser.phl.internal (Postfix, from userid 501) id 3D311780076; Fri, 24 Oct 2025 00:24:36 -0400 (EDT)
X-Mailer: MessagingEngine.com Webmail Interface
MIME-Version: 1.0
X-ThreadId: An5MunO63raJ
Date: Fri, 24 Oct 2025 15:24:15 +1100
From: Neil Jenkins <neilj@fastmailteam.com>
To: IETF JMAP Mailing List <jmap@ietf.org>
Message-Id: <bbc34c86-0ff7-4c95-96f4-1679032991c1@dogfoodapp.fastmail.com>
In-Reply-To: <7A250971-CC56-4D31-9B23-058B29A38E68@stalw.art>
References: <101DEC25-A12F-4063-90FB-446C6E5190BF@stalw.art> <4aa2017d-5ef4-486f-a264-2c8e2bec6094@dogfoodapp.fastmail.com> <34E1318A-C0D3-495F-9076-6B914C60D59F@stalw.art> <4561708e-c41a-4ef5-a644-0444eabbc083@dogfoodapp.fastmail.com> <7A250971-CC56-4D31-9B23-058B29A38E68@stalw.art>
Content-Type: multipart/alternative; boundary="7196b38d02c94e89882da963d19e8a77"
Message-ID-Hash: 7APN4RRSTDBQIZPOMCRTPAGWMFRZXOKK
X-Message-ID-Hash: 7APN4RRSTDBQIZPOMCRTPAGWMFRZXOKK
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: [JMAP] Re: JMAP for Calendars comments
List-Id: JSON Meta Access Protocol <jmap.ietf.org>
Archived-At: <https://mailarchive.ietf.org/arch/msg/jmap/HzgkF10lfEjbf-LZ6k6WxOllR0s>
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>

Apologies for the delay in getting back to this.

On Fri, 10 Oct 2025, at 20:06, Mauro De Gennaro wrote:
> For this use case, I’m thinking from the perspective of a calendar client implementer. For example, suppose the client UI lists all participants in an event, and the user can right-click on a participant to view their availability or share something else (a file node, mailbox, etc.) with them before the meeting. As you said, the client only knows the participant’s alias and display name.
> 
> Currently, the only way for the user to locate the corresponding principal (so they can view availability or share data) is to close that view and perform a manual search by name or by calendar address (if it’s a mailto: URI and happens to match the principal’s email). Allowing Principal/query to search by calendarAddress would let clients automatically map a known calendar address to its principal, when that mapping exists.

OK, I've added:
*2.3. Principal/query extension
*
The following extra optional property is added to the *FilterCondition* object for the *Principal/query* method when the `urn:ietf:params:jmap:principals:availability` capability is used:

*calendarAddress*: String
    The given string is a calendarAddress belonging to the Principal.

Does that work for you?

> Just to clarify the model in Stalwart: when a Principal is a member of a group, they also own the group’s account data in addition to their own.

That's not how that was intended to work. An account can only be owned by a single Principal, so it should either be a group principal representing the group, or no owner (both are allowed). It sounds like you're returning a different owner depending on who's accessing the account? What was the idea behind that?

> It’s also possible for a group to share data with an individual Principal, in which case that Principal does not own the shared data.

Sorry, I don't understand what you're trying to differentiate here. Can you elaborate?

>> If the "timeZone" property of the event is null, then yes. If not-null, it should be translated into local time using whatever time zone was set by that property. By "The server's current time zone information" I just meant the current version of the IANA DB it has at the time. I agree this could be clearer.
> 
> Ah, so the client must also provide a timeZone property when using utcStart and utcEnd?
> 
> If so, the sentence “If set, the server will convert the UTC date to the event’s current time zone and store the local time” could be clearer. Perhaps it should explicitly state that when creating a new event:
> 
> - the client should provide a timeZone property,
> - if missing, the calendar’s default time zone is used, and
> - if the calendar has no default, then Etc/GMT is assumed.

Yeah, that's reasonable. I've changed it to:
*
*
*If set, the server will convert the UTC date to the event's current time zone and store the local time. If the event does not have a non-null "timeZone" property, the server MUST also set this property (and return it in the created/updated response, as per RFC8620, Section 5.3 <https://www.rfc-editor.org/rfc/rfc8620.html#section-5.3>). The value MUST be the "timeZone" property of the Calendar(s) the event is in if all of them have the same non-null value. Otherwise, the time zone is to be set to "Etc/UTC".*

>>>  • *Conflicting calendar defaults:* When an event is added to multiple calendars with different default alerts, time zones, etc., how should these preferences be applied?
>>> 
>> The time zone one is trickier, and is not currently defined in the spec I think. So if you have an event without a time zone, and it's in multiple calendars with different default time zone properties … err, I have no idea what you should do. I think all you can do is pick one, and try to make it stable? Any other suggestions?
> 
> Yes, it’s a tricky case. In my implementation, I choose the most common time zone among the calendars. If there’s no clear majority, I fall back to the time zone from the first calendarId associated with the event.

That sounds fine, I think.

> What are the intended use cases for systems that have multiple accounts containing principals?

It's going to be very rare, but most likely if you were proxying multiple systems into a single JMAP endpoint.

> Could the accountId parameter perhaps be made optional on Principal/* methods to simplify the more common single-directory scenario?

I think it should be mandatory for consistency with the rest of JMAP. (I remember we had a big discussion about whether it should always be optional, defaulting to the primary account for the data type, and we decided to follow the principle of always being explicit, which guards against edge cases like the primary account changing on the server).

>>>  • It’s unclear what `busyStatus` should be used when `participationStatus` is `needsAction`, `tentative` (and maybe also that `delegated should not be included`).
>> `"tentative"` — The event status is "tentative" or the Principal's "participationStatus" is "tentative".
>> 
>> That's an "or", so if the event status is tentative, the busyStatus here would be tentative, according to the spec. (Or have I misunderstood your question?)
> 
> I was referring to the busyStatus of the BusyPeriod object, which can be confirmed, tentative, or unavailable. My question was which value should be used when the participant’s participationStatus is needsAction (I mistakenly included tentative earlier). It might also be worth clarifying (though perhaps it’s obvious) that when participation is delegated, the participant should be considered available during that time.
> 
> […}
> Please disregard this comment. I had been expecting a direct mapping between participationStatus and busyStatus, but after re-reading the relevant event criteria, I see that it clearly states only events with a participationStatus of "accepted" or "tentative" are included.

Just to clarify, if the calendar's "includeInAvailability" property for the user is "attending", then yes, only events with an accepted or tentative participation status will be included. If the calendar's "includeInAvailability" property is "all", then the event would be included even if the user is not a participant, or their participation status is "needs-action".

> Out of curiosity, what was the reasoning for leaving Tasks out of the spec? The current methods in JMAP Calendars already seem well suited for Tasks with only minor extensions.

To keep the spec simpler and cleaner (and it's long enough already). I expect a Tasks spec would be similar in many ways, but it's a different use case and has slightly different requirements (VJOURNAL gets even more into the weeds).

>>>  • *CalendarEvent/query:* The `cannotCalculateOccurrences` error seems to cover general recurrence failures. Would it be useful to define a specific error when a recurrence range expansion is too large?
>>> 
>> You mean if it exceeds the *maxExpandedQueryDuration* duration (found in the capabilities)? Yeah, that should maybe have a different error type.
> 
> Yes, exactly.

OK, I've added a new `expandDurationTooLarge` error type for this.

(Changes will be published when draft submission reopens in a week or so.)

Cheers,
Neil.