[Jmap] Re: Mahesh Jethanandani's Discuss on draft-ietf-jmap-contacts-09: (with DISCUSS and COMMENT)

Mahesh Jethanandani <mjethanandani@gmail.com> Sun, 02 June 2024 22:31 UTC

Return-Path: <mjethanandani@gmail.com>
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 9411DC14F61A; Sun, 2 Jun 2024 15:31:54 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.094
X-Spam-Level:
X-Spam-Status: No, score=-2.094 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, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_ZEN_BLOCKED_OPENDNS=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001, URIBL_DBL_BLOCKED_OPENDNS=0.001, URIBL_ZEN_BLOCKED_OPENDNS=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([50.223.129.194]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Oq9D3ra71a_8; Sun, 2 Jun 2024 15:31:50 -0700 (PDT)
Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 1720DC14F603; Sun, 2 Jun 2024 15:31:50 -0700 (PDT)
Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-7024cd9dd3dso1661483b3a.3; Sun, 02 Jun 2024 15:31:50 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1717367509; x=1717972309; darn=ietf.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=hrhM/hGHdPPIVTIMt1pAfL8L7OLhKNcEBBEDpmiZeZI=; b=cI4m/rRCI9sAzdd4gKnqkSqtE1QyhyRACPzcG1j/pHp/zGlaTxqL00Bi9w8vfqVIdi ZoqBgaQMWBA//stJ5fcMSbWjjk3ML+0uI+3qRgfcssFUVWFWuyMzWQeSI1NzKDfPVP0F tL6tPDYuky+uJTLLJBkB+XyfknnIpFRXklZCCzF0BGoORXDCJIYru3ldCys53gxeQHvN PsXH45XFMdgzCObgYjDY5Mke9XMpK9n5vawZXK/rh3fnlMyycuglVpDRB2Py+CSVCkrz PHqqVH595uBVnN4L4kCbu7xn9dubmmKx6+ZH45miB1UwZdgXMhbtl//u/ASQb9Vql1yN dc1A==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717367509; x=1717972309; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hrhM/hGHdPPIVTIMt1pAfL8L7OLhKNcEBBEDpmiZeZI=; b=fkM7+4RPWhqAiD4D62QNPOIFKtK0iQjrynjIAs29ouO4ZUaqgj4KEq60b6ENpxuMHh G3mgikjMAmWpMo4Kyufu4NgH7uq1kIQzj6inPMs+n1STpbv1WPrGyTzYMD9HdRch44FD G3zK75honYiRFUIAmxA13zCUOau6VCQ6itpUAxl0cLlN4j0+0jVLV1Nl2xuIHNkkWtcz is9E7Ze6R9+Mx6acr1h8CmuA7eBU8Yczo+yaFidVXfTl2hP23JmV+6dnwjFB/N0WSStu aSOAX1GbSBcbqDjx2aG4NbKSNwV8xtOHan2WRS3BgjZZYGr8LGXjK30VvRbe3obmKsVV xU8w==
X-Forwarded-Encrypted: i=1; AJvYcCVSxixioe5i7Ol75xFwJP8DKqy7Bz8XTcj3ZyoDJJpzmF2WhnSZgHBWEP7gvSo+7Fa0NIT3bEbomxvtK0SV5S/wqjZ9lE/Za24MU1uXhqBORNo0zAItEPpmeIxjZFfoociY1SgizIf7lVqqOHkyXOA8qIuxPC/t
X-Gm-Message-State: AOJu0Yxo0o79eSZhRvJx6a6bWy//R48dc0/y15LpuMZgDe+LybA5kppH m1dNMG2HFArFDU3uCo2TFymp5fUtgW/IRlbmea5lQSTN0e4repzP
X-Google-Smtp-Source: AGHT+IGn7s7mVo5Nn3TnX/ob0rdib94HmmUv801yMCDvCSn341k7Y+KT+p3iSbxUQXdRkTzCCgmHJw==
X-Received: by 2002:a05:6a00:130c:b0:6ea:ed70:46b4 with SMTP id d2e1a72fcca58-702478f7c71mr7118022b3a.29.1717367509055; Sun, 02 Jun 2024 15:31:49 -0700 (PDT)
Received: from smtpclient.apple (c-69-181-169-15.hsd1.ca.comcast.net. [69.181.169.15]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-70254ef605asm2627761b3a.169.2024.06.02.15.31.47 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 02 Jun 2024 15:31:48 -0700 (PDT)
From: Mahesh Jethanandani <mjethanandani@gmail.com>
Message-Id: <1962CBFE-3ECB-436D-959D-23DFD60AA303@gmail.com>
Content-Type: multipart/alternative; boundary="Apple-Mail=_2D89651D-F6BE-494C-96C1-81B79FB8F781"
Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.8\))
Date: Sun, 02 Jun 2024 15:31:46 -0700
In-Reply-To: <7a00bc9d-d339-4a31-b566-12ceaf3841d5@dogfoodapp.fastmail.com>
To: Neil Jenkins <neilj@fastmailteam.com>
References: <171625301728.10738.743002934797335476@ietfa.amsl.com> <7a00bc9d-d339-4a31-b566-12ceaf3841d5@dogfoodapp.fastmail.com>
X-Mailer: Apple Mail (2.3696.120.41.1.8)
Message-ID-Hash: ZXUIE2B4HP4AYRS253DF7DB7JZT4LPOY
X-Message-ID-Hash: ZXUIE2B4HP4AYRS253DF7DB7JZT4LPOY
X-MailFrom: mjethanandani@gmail.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
CC: The IESG <iesg@ietf.org>, draft-ietf-jmap-contacts@ietf.org, jmap-chairs@ietf.org, IETF JMAP Mailing List <jmap@ietf.org>, Jim Fenton <fenton@bluepopcorn.net>
X-Mailman-Version: 3.3.9rc4
Precedence: list
Subject: [Jmap] Re: Mahesh Jethanandani's Discuss on draft-ietf-jmap-contacts-09: (with DISCUSS and COMMENT)
List-Id: JSON Message Access Protocol <jmap.ietf.org>
Archived-At: <https://mailarchive.ietf.org/arch/msg/jmap/RmPaYBP_nI9LE4qk82yhMIHIkbg>
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,

My responses inline.

> On May 31, 2024, at 7:07 AM, Neil Jenkins <neilj@fastmailteam.com> wrote:
> 
> Hi Mahesh,
> 
> Thank you for your review.
> 
> On Tue, 21 May 2024, at 10:56, Mahesh Jethanandani via Datatracker wrote:
>> Section 2.3, paragraph 3
>> >       If false, any attempt to destroy an AddressBook that still has
>> >       ContactCard in it will be rejected with an addressBookHasContents
>> >       SetError.  If true, any ContactCards that were in the AddressBook
>> >       will be removed from it, and if in no other AddressBooks they will
>> >       be destroyed.
>> 
>> The "if true" condition is not clear to me, especially if other AddressBooks
>> exist. There is a distinction that is being drawn between removing a
>> ContactCard and destroying it, which is not apparent. Can that distinction be
>> explained?
> 
> I will explain, but I'm not sure how to reword this to make it more obvious. Quoting from the data model overview <https://www.ietf.org/archive/id/draft-ietf-jmap-contacts-09.html#name-data-model-overview>:
> 
> A ContactCard is a representation of a person, company, or other entity, or a group of such entities […]. Each ContactCard belongs to one or more AddressBooks.
> 
> And from the definition of ContactCard <https://www.ietf.org/archive/id/draft-ietf-jmap-contacts-09.html#name-contactcards>:
> addressBookIds: Id[Boolean]
> The set of AddressBook ids this ContactCard belongs to. A card MUST belong to at least one AddressBook at all times (until it is destroyed).
> So the way ContactCards are associated with AddressBook objects is via a property on the ContactCard. The API enforces consistency — you can't have an id in the ContactCard's addressBookIds property that's not a currently valid AddressBook. So if you try to destroy an AddressBook that is currently referenced by a ContactCard we can do one of two things to ensure the data remains consistent:
> Reject the destroy (this is the default).
> Update the ContactCards that currently reference the AddressBook. This is what happens if you set onDestroyRemoveContents to true. It removes the now non-existent AddressBook id from the ContactCard's addressBookIds property. But all ContactCards MUST be associated with at least one AddressBook at all times, so if this was the only AddressBook it was in, we will destroy the ContactCard instead to ensure the data consistency constraints are upheld.
> Intuitively you can think of it like this: every contact is in an address book. If you delete the address book, it cascades the delete to the contacts in it, except for those that are still in another (non-deleted) address book.
> 
> Does that clarify? I think that the original text will probably be clear enough for anyone implementing this, who will probably have more time to understand the whole data model first. But I am open to suggestions on how to reword this to make it easier to parse without deeper understanding.

Thanks for that explanation. How about this?

OLD:
If false, any attempt to destroy an AddressBook that still has ContactCard in it will be rejected with an addressBookHasContentsSetError. If true, any ContactCards that were in the AddressBook will be removed from it, and if in no other AddressBooks they will be destroyed.

NEW:
If false, any attempt to destroy an AddressBook that still has ContactCard in it will be rejected with an addressBookHasContentsSetError. If true, any ContactCard that is in the AddressBook that is set to be destroyed. will be removed from it, and if the ContactCard does not exist in any other AddressBooks it will be destroyed.


> 
>> Related to that, it appears the ContactCards that were part of an AddressBook
>> that is being deleted, will be moved if another AddressBook exists.
> 
> As per the above, that's not correct. The ContactCard may already be in another AddressBook as well (think of the AddressBooks as more like labels in this regard), however it will not be automatically added to another one.
> 
>> Section 3, paragraph 2
>> >    *  *addressBookIds*: Id[Boolean]
>> >       The set of AddressBook ids this ContactCard belongs to.  A card
>> >       MUST belong to at least one AddressBook at all times (until it is
>> >       destroyed).  The set is represented as an object, with each key
>> >       being an AddressBook id.  The value for each key in the object
>> >       MUST be true.
>> 
>> What happens if a ContactCard is removed from an AddressBook that is present in
>> multiple AddressBooks? Is it removed from all AddressBooks, or just one?
> 
> I'm not sure I fully understand your question here, but let me provide an example to perhaps clarify:
> 
> You have two AddressBooks in an account:
> Work
> Personal
> You have a ContactCard representing Bill. Bill is your friend and colleague, and you have placed him in both address books. Some things that could happen:
> Bill leaves the company. You update Bill's ContactCard (using a JMAP Contact/set method call) to change the addressBookIds property, removing Bill from the Work address book but leaving the card in your Personal address book.
> You leave the company. You destroy the Work AddressBook, with onDestroyRemoveContents set to true. Because Bill's contact is also in your Personal address book, it is implicitly updated as above (to remove it from the now-destroyed Work AddressBook), but otherwise unchanged. Any contacts just in the Work AddressBook will have been destroyed.
> Bill leaves the company and you have a massive fight, to the point you are no longer friends. You destroy Bill's contact card (again, using a JMAP Contact/set method call).
> Does that help? If not, could you please rephrase to help me understand the question?

Sure. 

My question is about a ContactCard that is present in multiple AddressBooks. Take your example above, Bill appears in two AddressBooks, Work and Personal. And I will take the example of Apple’s Contacts App that I use. I use the search capability in the App to find the ContactCard for Bill, find it, select it, and hit the delete button. What happens?

Per your explanation above, I am not sure what will happen. Because per the description, the only way to delete Bill is for me is to select the AddressBook called Work, find Bill, remove it, then select AddressBook Personal, find Bill again, and then remove it. Then and only then Bill's ContactCard will be destroyed. Is that true?

> 
>> If it is removed from all AddressBooks, how does a user who wants to trim the
>> AddressBook to certain contacts remove a ContactCard?
> 
> You can't update a ContactCard to not be in any AddressBook (that update would be rejected by the server). You can destroy the ContactCard instead.

My question is slightly different. Take your above example again. It was, what happens if I want to remove Bill from the Work AddressBook? But I think I got the answer from the example above. It will be removed from the Work AddressBook, but will remain in the Personal AddressBook.

Which brings me to the comment I made initially. You are making a distinction between removing a ContactCard, and destroying it. Based on all the explanations, what I understand is:

remove: A ContactCard can be removed from an AddressBook, but MAY NOT be destroyed.
destroy: Once a ContactCard is removed from the last AddressBook that it is existed it, it is destroyed

If this distinction sounds right, it would help to make that distinction clear up front.

Thanks.

> 
>> Section 2, paragraph 12
>> > w AddressBooks created by the user themself. If false, the AddressBook and it
>> >                                    ^^^^^^^^
>> Generally speaking, "themself" is only acceptable when referring to a singular
>> entity (such as the singular usage of "they", which is the preferred pronoun
>> for many non-binary people). If "themself" refers to a plural entity (such as
>> "everybody", or the standard usage of "they"), you should use "themselves".
> 
> As "the user" is singular, I believe the current wording is correct,
> 
>> Section 2.3, paragraph 3
>> > s, it MUST be ignored and the currently default AddressBook (if any) will rem
>> >                               ^^^^^^^^^^^^^^^^^
>> You used an adverb ("currently") instead of an adjective, or a noun ("default")
>> instead of another adjective.
> 
> I believe the current phrasing is clear and reasonable; I'll leave this and revisit if the RFC editors flag it.
> 
> Cheers,
> Neil.


Mahesh Jethanandani
mjethanandani@gmail.com