Skip to main content
Les contacts implémentent la RFC 9610 (urn:ietf:params:jmap:contacts), avec des fiches en objets JSContact (RFC 9553). Les mêmes données sont servies en CardDAV.

Objets et méthodes

Comportements à connaître

  • Le serveur possède l’uid. Un uid fourni par le client à la création est rejeté (invalidProperties) : c’est le serveur qui le frappe, ce qui rend la correspondance CardDAV sans ambiguïté.
  • addressBookIds est optionnel à la création : une appartenance omise classe la fiche dans le carnet par défaut.
  • L’historique de versions est de premier rang. ContactCard/getHistory liste les versions antérieures d’une fiche, restoreVersion en ramène une. Les modifications de n’importe quel protocole (JMAP ou CardDAV) sont versionnées pareil.
  • L’aller-retour est sans perte. Les composantes de nom et d’adresse se transposent complètement entre vCard (3.0/4.0) et JSContact dans les deux sens ; les propriétés vCard sans modèle JSContact sont préservées plutôt qu’abandonnées. Un PUT CardDAV qui dupliquerait un UID existant d’une autre source est refusé, jamais dupliqué en silence.
  • La dépréciation est annoncée honnêtement. L’objet de capacité du compte annonce la posture du modèle AddressBook pour que les clients s’adaptent, au lieu de découvrir le comportement par essais.

Les annuaires de tenant

Une organisation peut publier des jeux de contacts partagés (« Clients », « Personnel ») tenus sur le plan d’administration. Le choix de conception qui structure toute la surface : un annuaire n’est pas un conteneur dans lequel les membres classent des fiches. Les membres ne voient aucun conteneur. Ce qu’un membre voit, c’est son propre carnet d’adresses, où les entrées arrivent en fiches lisibles seulement, avec source: "organization" et directorySource: "tenant:<directoryId>" : le plan même qu’alimente un connecteur LDAP ou SCIM externe. Un client qui affiche déjà les contacts d’origine organisationnelle n’a aucun écran à ajouter. Qui écrit quoi. Les objets annuaire sont réservés au rôle d’administrateur de tenant. Les entrées sont réservées aux editorIds de leur annuaire, qui sont des identifiants de principal : y nommer un groupe est valide et courant, et l’appartenance est résolue par l’expansion des bénéficiaires au moment du contrôle d’accès, jamais stockée déjà expansée. Ajouter quelqu’un à un groupe lui donne donc le droit d’éditer sans toucher à l’annuaire. Deux comportements à connaître avant de bâtir dessus :
  • mayEdit est calculé pour vous, et vous ne pouvez pas le calculer vous-même. Il suit le rôle de tenant de l’appelant et l’expansion de groupes côté serveur : deux comptes lisent donc légitimement des valeurs différentes pour le même annuaire, et le dériver depuis editorIds est impossible, cette liste étant aveugle à l’appartenance aux groupes par conception. C’est exactement pour cela qu’il est déclaré dans le canon publié au lieu d’être laissé à la déduction depuis le type TypeScript.
  • La comptabilité du serveur ne vous appartient pas. La propriété card porte la fiche JSContact et rien d’autre : les clés de projection comme source ou directoryId posées à l’intérieur sont refusées, pas écrasées en silence.
Le contenu d’un annuaire est une donnée de l’organisation, pas une donnée personnelle détenue pour le compte d’un membre : il se purge en supprimant des entrées, et il ne suit pas l’effacement d’un compte individuel. Les règles de rigueur sont identiques à la surface courrier : identifiants inconnus dans notFound, invalidProperties plutôt qu’une coercition, accountNotFound, stateMismatch.