urn:oximail:params:jmap:v2:*. Cette page décrit la surface telle que construite : ce que le serveur négocie et sert réellement en v0.30.0. Les extensions sont en cours de rédaction comme Internet-Drafts destinés à l’IETF ; voir drafts IETF pour le programme.
Comment v2 se négocie
v2 n’est pas un commutateur de version : c’est un opt-in par capacité, exactement comme n’importe quelle capacité JMAP :- Un client demande une capacité v2 dans
using; les méthodes qu’elle déverrouille deviennent appelables dans cette requête. Rien ne change au comportement v1 pour les clients qui ne demandent jamais. - Les noms de méthodes sont des alias à double capacité quand une capacité v1 et une v2 couvrent le même handler : le registre fait correspondre les deux écritures à une seule implémentation, il y a donc exactement un comportement par méthode, quelle que soit la capacité qui l’a déverrouillée.
- L’ensemble d’exclusion mutuelle est vide en v0.30.0 : associer une capacité v1 à son homologue v2 dans la même requête est permis (voir JMAP Core pour le mécanisme).
- Comme partout ailleurs, l’objet de session fait foi : l’entrée
accountCapabilitiesde chaque compte pour un URN v2 porte les limites et options annoncées de cette capacité. Détectez les fonctionnalités depuis la session, jamais depuis la version du serveur.
Les objets de capacité v2
Pour chaque capacité, le contrat de fil qui fait foi est ce que la session annonce, plus les comportements des méthodes. Les règles de rigueur (page courrier) s’appliquent aux méthodes v2 à l’identique : arguments et propriétés inconnus sont des erreurs, jamais ignorés en silence.
Ce que les objets de capacité annoncent
Les objets de capacité de la session se décrivent eux-mêmes : les clients construisent leur interface à partir d’eux, au lieu de coder en dur une connaissance du serveur. Les entrées porteuses telles que servies en v0.30.0 :v2:rulesporte tout le vocabulaire de l’éditeur de règles :supportedFields(18 champs de condition) etsupportedActions(15 types d’action), un client construit son éditeur depuis ces listes, plus les bornes appliquées (maxRulesPerAccount: 1000,maxActionsPerRule: 20,maxConditionDepth: 20,maxRuleNameLength: 256,perRuleExecutionTimeoutMs,maxApplyEmailsPerCall).v2:adminn’apparaît dansaccountCapabilitiesque pour les comptes au rôle administrateur : son absence est ce qui dit au client de ne pas afficher de surface d’administration. Elle annoncesupportedPrincipalRoles, les faits de rétention (softDeleteRetentionDays: 30,auditLogRetentionDays: 2557, soit sept ans) etmfaRequiredForSensitiveOperations: true: les changements de rôle et les mutations de tenant par un compte qui a enrôlé une passkey exigent une session authentifiée par passkey.urn:ietf:params:jmap:auditlog(réservée aux administrateurs commev2:admin) annonce le journal d’audit inviolable :{hashAlgorithm: "sha-256", verificationSupported: true, retentionDays: 2557}.AuditEvent/verifyrecalcule la chaîne de hachage et signale la première entrée altérée ou manquante.v2:mailannonce les bornes d’envoi appliquées :maxSizeEmail(50 Mio, aussi pré-annoncée par l’extension SMTPSIZE),maxScheduleDelay(un an sur lesendAtd’Email/send) etemailQuerySortOptions, le vocabulaire de tri exact qu’accepteEmail/query. L’objet Email v2 porte aussiexpiresAt(mise à la corbeille automatique à l’instant choisi), etEmail/sendaccepterequestMdn(accusés de lecture RFC 8098) ettlsRequired(REQUIRETLS RFC 8689, y compris pour les envois programmés).v2:streamingannoncereplayWindowSeconds(l’horizon réel de rétention du journal de changements, 90 jours : unPush/catchupdepuis n’importe quel état dans la fenêtre rejoue exactement ce qui a été manqué),maxQueryStreamChunk: 1000et la cadence de vérification des abonnements push.v2:push-patchesannoncemaxPatchSize(1 Mio),maxBatchEntries: 100,maxPatchesPerSecond: 10,supportedTransports: ["websocket"]etmaxConcurrentStreams: 0(pas de flux de requête poussés par le serveur : leCore/queryStreamcadencé par le client est le mode de flux). Un client s’abonne par connexion WebSocket avecEnablePushPatches {types, properties}; les entréesupdatedportent alors exactement les propriétés changées, et les cas dégradés retombent sur un simpleStateChange(réconciliation parPush/catchup).v2:resource-limitsn’annonce plus que des limites qu’un mécanisme applique réellement, depuis les mêmes constantes que les gestionnaires : dontmaxTotalRequestsPerMinute, injectée depuis la configuration effective de limitation de débit de l’opérateur (absente quand aucun limiteur ne tourne).maxConcurrentRequestsvit sur la capacité core (RFC 8620) et s’applique par compte sur les deux transports JMAP.
muted par fil (hérité par les messages nouvellement ingérés) et pinned, Thread/split, Thread/merge, et /queryChanges sur chaque type v2 interrogeable.
Le canon de projection
Chaque/get valide son argument properties contre un vocabulaire fermé, propre au type, et avant toute lecture du magasin. Un nom inconnu revient en invalidArguments qui nomme les fautifs ; id est toujours accepté (la RFC 8621 le rend implicite) et * sélectionne toutes les propriétés de premier niveau.
C’est une erreur, et non un haussement d’épaules, pour une raison précise. Avec l’ancien motif « sérialiser puis filtrer », une propriété mal orthographiée produisait un succès avec la propriété absente : indiscernable d’une propriété que le serveur aurait choisi de ne pas servir. Un client ne pouvait pas distinguer sa faute de frappe d’une limite du serveur, et personne ne le pouvait davantage en lisant les journaux.
Un vocabulaire fermé ne sert que si on peut le lire : le canon est donc publié en forme machine, à côté des types TypeScript générés.
DERIVED_<Type> est la partie qu’un client ne peut pas reconstituer seul. Le mayEdit d’un annuaire de tenant est calculé par appelant depuis son rôle de tenant et une expansion de groupes côté serveur ; aucun champ de structure ne le porte, et le type TypeScript seul n’en dit donc rien. Le registre ne liste que de vraies injections hors structure : une propriété qui est un champ de structure réécrit par lecteur, comme myRights, est déjà typée et en est délibérément absente.
Le canon publié est un contrat additif seulement, la même règle que la surface --json de la ligne de commande. La capacité v2:projection de la session est le marqueur de conformité qui atteste que le modèle vaut pour tous les types.
Stabilité du fil : au sein de la ligne v0.30, les formes v2 évoluent de façon additive : nouvelles propriétés optionnelles et nouvelles méthodes, pas de renommage ni de changement de sémantique des champs servis. Les durcissements qui transforment un argument jusque-là ignoré en erreur sont étagés (journalisation d’abord, rejet une fois les clients confirmés propres).