Résumé

  • draft-ietf-jmap-object-history-00 permet à Foo/get de rendre des versions antérieures et détruites, mais laisse le serveur regrouper des modifications rapprochées, supprimer des versions dans n’importe quel ordre et abandonner silencieusement l’historique sous pression de stockage.
  • Un instantané récupéré aide à restaurer un état. Il n’établit ni l’auteur, ni la requête, ni la décision d’autorisation, ni l’effet obtenu ; même hasMoreHistory: false ne certifie pas que l’historique est complet.

Un carnet d’adresses peut retrouver le numéro supprimé hier. Une boîte aux lettres peut afficher le message tel qu’il existait juste avant sa destruction. Cette capacité est concrète : elle rend une erreur réversible sans obliger chaque client à inventer son propre entrepôt de sauvegarde.

L’interface peut pourtant donner une impression de preuve qu’elle ne promet pas. Même identifiant, numéro de version, date de remplacement : l’écran ressemble vite à une chronologie définitive. Or aucune de ces valeurs ne dit qui a effectué le changement, quel logiciel a envoyé la mutation, quelle règle l’a autorisée ni ce qui s’est produit ensuite.

C’est la frontière à retenir dans JMAP Object History, déposé sous le nom du groupe de travail le 15 septembre. Le texte rend un ancien état interrogeable. Il ne transforme pas un magasin de récupération en journal d’audit.

Des états conservés, et non la suite des événements

Le socle JMAP organise les méthodes par type d’objet : Foo/get, Foo/changes, Foo/set, Foo/query et Foo/queryChanges. Il sait déjà synchroniser l’état courant. Foo/changes indique quels identifiants ont changé entre deux états, sans restituer les anciennes valeurs.

La capacité urn:ietf:params:jmap:object-history étend Foo/get. includeReplaced: true ajoute des représentations remplacées à l’objet vivant. includeDestroyed: true permet de demander des objets qui n’existent plus. En combinant les deux, le serveur peut rendre toutes les versions qu’il a encore gardées pour un objet détruit.

Chaque représentation conserve l’identifiant de l’objet. objectHistory.version les ordonne dans la réponse ; objectHistory.replaced indique quand une représentation a cédé la place à une mise à jour ou à une destruction. Une valeur nulle signale la version vivante.

Ce sont des coordonnées d’état. L’horodatage ne révèle pas quand la version avait été créée. Le numéro ne désigne pas une transaction. Aucun champ ne porte l’identité de l’acteur, la session, l’appareil, le corps de la requête, la politique appliquée, l’approbation, la notification ou l’effet externe.

Comparer deux images successives montre une différence. Cela ne démontre pas qu’une seule action atomique a produit cette différence.

Le chaînon manquant peut n’avoir jamais existé

Le projet autorise explicitement le regroupement de plusieurs mises à jour rapides en une seule version historique. Trois corrections rapprochées d’un numéro de téléphone peuvent ne laisser que l’état avant la séquence et l’état après celle-ci. L’événement intermédiaire n’est pas forcément caché : il se peut qu’aucune représentation séparée n’ait été créée.

Le serveur peut aussi élaguer d’anciennes versions dans l’ordre qu’il choisit. Des trous dans la numérotation sont valides et le client ne doit présumer ni continuité ni exhaustivité. Une version absente peut donc avoir été omise dès l’origine ou supprimée plus tard ; la réponse ne permet pas de trancher.

Même le numéro de version est volontairement modeste. Le serveur devrait rester cohérent, mais le client ne doit pas dépendre d’une stabilité entre requêtes. Ce nombre sert d’abord à classer les variantes d’un même objet à l’intérieur d’une réponse. En faire l’identifiant durable d’un événement d’audit reviendrait à exiger une propriété que le texte refuse de garantir.

Ce choix ménage le stockage. Il interdit aussi de traduire « versions disponibles » par « tout ce qui s’est passé » sans une seconde source d’événements.

hasMoreHistory renseigne une récupération, pas son exhaustivité

historyLimit limite le nombre total d’entrées et demande les versions les plus récentes. Si cette limite est atteinte pour au moins un identifiant, hasMoreHistory: true indique que des éléments plus anciens sont alors disponibles. Dans une requête portant sur plusieurs objets, il ne précise pas lequel ; il faut les interroger séparément.

Le vrai n’est qu’un instantané. Le projet avertit que les entrées restantes peuvent être purgées avant la requête suivante. Le drapeau décrit une possibilité au moment de la réponse, pas une réservation de données.

Le faux est encore moins probant. Il signifie normalement que tout l’historique conservé a été rendu. Le serveur peut néanmoins répondre faux alors qu’il reste des éléments si les découvrir efficacement est difficile. Et, dans tous les cas, il ne dit ni que chaque changement a été enregistré, ni qu’aucune version n’a été élaguée.

Une console qui affiche « audit complet » à partir de cette valeur inverse le contrat. La formulation défendable est : aucun historique conservé supplémentaire n’a été signalé dans cette réponse.

Une durée nulle ne signifie pas une conservation éternelle

Le compte qui annonce la capacité publie maxHistoryDuration. Une valeur numérique donne l’âge maximal, en secondes après remplacement, au-delà duquel une version peut avoir disparu. La valeur nulle signifie que le serveur n’applique pas de limite temporelle.

Elle ne promet pas la permanence. La section de sécurité prévoit qu’une contrainte de capacité puisse conduire à jeter l’historique sans notification. Le temps est une politique de rétention ; le volume en est une autre. Un type d’objet peut même exposer l’interface tout en ne gardant aucune version antérieure : l’objet courant est alors rendu avec objectHistory, éventuellement avec le numéro 1.

La présence de la capacité prouve donc une interface, pas un fonds d’archives minimal. Un besoin réglementaire ou contractuel doit spécifier sa propre durée minimale, l’export, l’intégrité, la notification de suppression et le gel juridique.

Restaurer et rendre des comptes demandent des reçus différents

Pour la récupération, le modèle est adapté. Email/changes peut indiquer quels identifiants ont été détruits ; Email/get peut ensuite demander ces objets avec includeDestroyed et présenter leur dernier contenu. L’utilisateur récupère ce qui lui manque sans faire croire que l’objet supprimé est encore vivant.

Pour attribuer une action, la réponse ne suffit pas. Un reçu sérieux doit relier l’acteur authentifié et sa session, le client et l’appareil d’origine, le corps exact de la mutation, le jeton d’état conditionnel, la version de politique et sa décision, la transaction acceptée par le serveur, les empreintes avant et après, l’identifiant durable d’événement, la notification et le résultat observé.

L’historique d’objet peut fournir l’une des représentations. Il ne remplit pas les autres colonnes. Déduire l’auteur du propriétaire de l’objet est dangereux. Déduire l’autorisation d’un changement visible oublie la politique réellement appliquée. Déduire un effet externe d’une valeur stockée confond acceptation par le plan de contrôle et exécution dans le monde réel.

Lorsque la responsabilité compte, l’architecture doit joindre les instantanés de récupération à un journal d’événements append-only. Elle ne doit pas prétendre qu’un même stockage satisfait deux contrats contradictoires.

Le droit historique ne se déduit pas du droit présent

Le passé pose aussi un problème d’autorisation. Le texte interdit de lire l’historique d’un objet que l’on n’a pas le droit de lire actuellement. Si les permissions ont varié, le serveur ne doit restituer que les versions auxquelles ce demandeur aurait eu droit à l’époque.

Cette règle empêche un lecteur récemment autorisé de voir des données d’une période où il ne l’était pas. Elle impose aussi de conserver suffisamment de contexte d’autorisation historique. Une liste de contrôle actuelle ne permet pas toujours de reconstruire la réponse correcte.

JMAP Sharing distingue déjà les principaux, l’intention de partage et l’accès effectif. Object History ajoute le temps : voir une ancienne version dépend d’un ancien droit, pas seulement de la carte shareWith actuelle. Une version rendue prouve que le serveur a décidé de la divulguer selon son évaluation ; elle n’explique pas entièrement cette décision si celle-ci n’est pas enregistrée ailleurs.

Un historique correct peut être volontairement incomplet

Une ancienne représentation peut conserver précisément l’information qu’un utilisateur ou un administrateur voulait effacer. Un numéro retiré d’un contact peut demeurer accessible dans l’historique. Le projet recommande donc un moyen administratif de purger les versions d’objets déterminés pour satisfaire la vie privée ou la conformité.

Cette tension doit être formulée, non masquée. Récupération, responsabilité, effacement et coût de stockage ne poussent pas dans la même direction. Chaque classe de données doit préciser l’objectif prioritaire, l’autorité qui peut autoriser une purge, la trace non falsifiable qui peut survivre et les faits d’audit indépendants qui restent après l’effacement du contenu.

Promettre un « historique immuable » sur une interface conçue pour permettre la suppression serait trompeur. Supprimer toute récupération parce qu’elle n’est pas médico-légale le serait aussi. La solution consiste à séparer les magasins et à publier leurs limites.

L’adoption par le groupe ne vaut pas déploiement

Le document de septembre est presque identique au projet individuel de mars. Le corps du protocole n’apporte pas de nouvelle preuve d’exploitation ; le changement significatif est le passage sous le nom du groupe JMAP.

Datatracker le classe comme document du groupe à l’étape I-D Exists. Aucun directeur de zone responsable, rapporteur ou téléconférence n’est indiqué. Le résumé ne renseigne pas le statut visé, alors que l’en-tête du projet affiche Standards Track. Il reste un Internet-Draft, pas un RFC, et les sources figées ne prouvent ni implémentation en production ni politique de conservation chez un service nommé.

Cette limite de maturité rappelle la règle d’exploitation. Une inscription au registre peut coordonner les logiciels. Seule l’observation du code en service dira quelles versions furent enregistrées, regroupées ou purgées, quelle autorisation fut appliquée et si une restauration a réellement abouti.

Sources