Résumé
- Le projet
draft-ietf-jmap-conditional-00distingue la condition portant sur des propriétés précises de l’atomicité portant sur toutes les mutations d’un mêmeFoo/set. - L’échange atomique de deux noms prouve qu’un état final a été validé sans application partielle. Il ne prouve ni le mandat de la personne qui l’a demandé, ni la propagation vers les systèmes extérieurs.
Deux objets frères portaient les noms current.txt et previous.txt. Une application voulait les permuter. Exécuté séparément, le premier renommage rencontrait le nom encore occupé par le second objet. Inverser l’ordre ne changeait rien : l’autre collision arrivait d’abord. Inventer un nom temporaire ajoutait un état visible que le métier n’avait jamais demandé.
L’état final, lui, respectait la contrainte d’unicité. Le problème venait de l’obligation de traverser un état intermédiaire illégal.
La révision 00 de JMAP Conditional Set, datée du 15 septembre 2026 et expirant le 19 mars 2027, propose une réponse. À la date de recherche, il s’agissait d’un Internet-Draft actif du groupe JMAP, destiné au Standards Track et susceptible de mettre à jour le RFC 8620 s’il était approuvé. Ce statut n’est ni un RFC définitif, ni une preuve d’implémentation ou d’usage en production.
Le texte ajoute deux mécanismes qui se ressemblent seulement de loin. ifUnchangedBy exprime des préconditions sur des propriétés choisies d’objets choisis. atomic:true demande que toutes les créations, mises à jour et destructions d’une méthode soient validées ensemble ou qu’aucune ne le soit. Confondre les deux ferait perdre précisément la discipline que le projet apporte.
Une condition décrit ce qui devait rester vrai
Le JMAP de base offre ifInState. Cette garde compare la chaîne d’état d’un type d’objet entier. Une arrivée de courrier, une modification sur un autre appareil ou une action du serveur peut changer cette chaîne sans toucher l’objet que le client souhaite modifier. La protection évite des écrasements, mais elle provoque aussi des rejets sans rapport avec la décision locale.
ifUnchangedBy réduit le périmètre. Le client fournit, pour chaque identifiant, un PatchObject contenant les valeurs attendues. La condition réussit lorsque l’application de ce patch à l’objet courant ne modifierait rien. null affirme l’absence d’une propriété. La comparaison reprend la représentation que Foo/get aurait renvoyée.
Le reçu est donc précis, mais étroit. Si la condition ne cite que blobId, un changement concurrent de nom peut être volontairement ignoré. Le succès signifie que blobId avait encore la valeur attendue au début de la méthode. Il ne signifie pas que l’objet entier était identique, encore moins que le contexte organisationnel n’avait pas changé.
Cette économie de conflit est utile. Elle impose en contrepartie de conserver la liste exacte des pointeurs contrôlés. Résumer le résultat par « version à jour » serait mensonger. Une condition sélective ne devient une comparaison globale que si le type fournit un jeton maintenu par le serveur et changé à chaque mutation. Même alors, la valeur probante dépend de la rigueur avec laquelle tous les chemins d’écriture font évoluer ce jeton.
La condition peut porter sur un objet du même type que la méthode ne modifie pas. Une mise à jour de fichier peut exiger que son parent conserve un identifiant et un nom donnés. Cela protège contre une écriture déposée dans un dossier déplacé ou renommé. Cela ne transforme pas deux propriétés en carte complète des droits, des ancêtres, des montages et des règles de conservation.
L’accès à la condition n’est pas un accès au secret
Le projet autorise les préconditions sur des propriétés lisibles mais non modifiables par le client : taille, identifiant de contenu ou horodatage maintenu par le serveur. Cette possibilité est puissante parce qu’elle permet de dépendre d’un fait que le client ne peut pas falsifier lui-même.
Elle pourrait aussi devenir un oracle. Si un client sans droit de lecture pouvait tester des valeurs cachées et observer succès ou échec, il apprendrait progressivement le secret. Le texte impose donc la même permission de lecture que Foo/get. Une propriété invisible doit produire forbidden, pas un résultat conditionnel.
Cette règle rappelle une distinction plus large. Pouvoir lire le fait servant de précondition ne donne pas le droit d’effectuer la mutation. L’autorisation d’écriture reste séparée. Un serveur peut constater que la valeur attendue est correcte puis rejeter l’opération pour absence de permission. L’état n’accorde pas un mandat.
Lorsqu’une seule condition échoue, toute la méthode est refusée avec stateMismatch. Aucune création, mise à jour ou destruction ne prend effet, et la chaîne d’état demeure inchangée. Le serveur peut nommer les identifiants en échec, sans révéler leurs valeurs. Le client doit relire puis décider ; il ne reçoit pas un conflit déjà résolu.
L’atomicité porte sur le résultat commun
L’option atomic:true traite un autre risque. JMAP Core peut appliquer séparément les éléments d’un Foo/set : certains réussissent, d’autres échouent. Pour une série de changements indépendants, ce comportement peut être acceptable. Pour l’échange de deux noms, il détruit l’invariant recherché.
Avec l’atomicité, le serveur évalue les contraintes sur l’ensemble final produit par toutes les modifications. Les deux noms peuvent être échangés parce que le résultat final n’a aucun doublon. Aucun état intermédiaire n’est présenté comme un résultat durable.
Si une partie échoue—patch invalide, collision, refus d’accès ou autre erreur de mutation—le serveur doit ne rien modifier et renvoyer atomicFailure. Les cartes d’erreur facultatives peuvent identifier la cause. Les identifiants absents de ces cartes n’ont pas été validés en silence : leurs changements ont eux aussi été abandonnés.
Une précondition fausse reste signalée par stateMismatch, même lorsque l’atomicité est demandée. Cela préserve les catégories d’évidence. Le point de départ attendu n’existait plus dans un cas ; les mutations demandées ne pouvaient pas constituer un tout valide dans l’autre.
Si le serveur ne sait pas appliquer cette méthode comme une unité, il doit renvoyer cannotApplyAtomically et ne rien faire. Il lui est interdit de retomber discrètement sur une exécution partielle. Cette absence de dégradation silencieuse protège davantage que beaucoup de promesses abstraites : le client sait que la garantie n’a pas été fournie.
Il peut ensuite réessayer sans atomic, mais seulement s’il tolère les succès partiels. Ce second appel n’est pas une répétition technique. Il modifie l’invariant. Une organisation sérieuse lui attribue un décideur, une justification et un plan de réconciliation différents.
Le serveur ne gouverne pas le sens du changement
L’échange atomique des noms établit qu’un serveur a validé deux mutations ensemble. Il ne répond pas à la question de savoir qui avait le droit métier d’inverser « courant » et « précédent ». L’authentification et les permissions de la requête comptent ; elles ne suffisent pas toujours à représenter l’autorité économique ou juridique sur le contenu.
Un compte technique peut posséder une permission trop large. Un automatisme peut être correctement authentifié et suivre une consigne devenue caduque. Un opérateur peut avoir le droit de modifier les objets sans pouvoir engager l’organisation sur leur signification. Le protocole fait bien de ne pas inventer ce mandat.
La discipline de Heng Lu demande que la couche commune reste mince. Ici, elle coordonne une comparaison et une validation transactionnelle. Elle ne doit pas devenir un souverain du fichier, du message ou du droit partagé. L’application garde la responsabilité d’identifier le principal, la règle et le dommage acceptable.
Le commit n’est pas l’observation finale
Une réponse atomique délimite le Foo/set du serveur. Elle n’englobe pas automatiquement un index de recherche, un cache de chemin, une notification, un agent hors ligne ou un service distant.
Après l’échange, un cache peut encore associer current.txt à l’ancien identifiant. Une interface peut afficher l’ordre précédent. Une notification peut arriver avant l’actualisation d’un index. Ces délais n’annulent pas le commit ; ils montrent simplement que le résultat métier exige d’autres reçus.
La bonne chaîne sépare la requête autorisée, les préconditions évaluées, le commit atomique, la lecture après écriture, la génération observée par chaque consommateur et le résultat auprès de l’utilisateur. Appeler tout cela « renommage réussi » économise des mots au prix de la capacité d’enquête.
Les tests doivent donc provoquer les formes d’échec. Modifier une propriété non sélectionnée et vérifier que la condition ciblée reste vraie. Modifier la propriété sélectionnée et vérifier l’absence totale de mutation. Tenter une propriété cachée et exiger forbidden. Créer une erreur sur une seule des deux opérations atomiques et vérifier que l’autre ne fuit pas. Retarder les caches après un commit réussi et observer que leur retard reste visible.
Deux noms peuvent être valides ensemble sans l’être successivement. Le projet sait exprimer cette vérité technique. La direction doit encore prouver qui avait le droit de la demander et où son effet a réellement été constaté.
Sources
- https://www.ietf.org/archive/id/draft-ietf-jmap-conditional-00.txt
- https://www.ietf.org/archive/id/draft-ietf-jmap-conditional-00.html
- https://www.ietf.org/archive/id/draft-ietf-jmap-conditional-00.xml
- https://datatracker.ietf.org/doc/draft-ietf-jmap-conditional/
- https://datatracker.ietf.org/doc/draft-ietf-jmap-conditional/history/
- https://datatracker.ietf.org/doc/draft-ietf-jmap-conditional/references/
- https://datatracker.ietf.org/api/v1/doc/document/draft-ietf-jmap-conditional/
- https://www.ietf.org/archive/id/draft-gondwana-jmap-conditional-00.txt
- https://www.ietf.org/archive/id/draft-ietf-jmap-filenode-14.txt
- https://www.rfc-editor.org/rfc/rfc8620.txt
- https://www.rfc-editor.org/rfc/rfc8620.html
- https://www.rfc-editor.org/rfc/rfc8620.json
- https://www.rfc-editor.org/rfc/rfc4918.txt
- https://www.rfc-editor.org/rfc/rfc9110.txt
- https://www.rfc-editor.org/rfc/rfc6902.txt
- https://www.rfc-editor.org/rfc/rfc8621.txt
Briefing des membres
Contexte approfondi du profil
Connectez-vous avec le bon niveau d'adhésion pour débloquer le briefing complet et les notes de source.
Réservé à Strategic Circle
Strategic Circle
Ouvert à tous les lecteurs. Débloquez les briefings de profil après adhésion et connexion.
Rejoindre Strategic CircleRéservé aux membres de Leadership Alliance
Leadership Alliance
Réservé aux propriétaires et dirigeants qualifiés d'actifs IP ; connectez-vous pour débloquer les briefings Alliance.
Rejoindre Leadership Alliance
