this repo has no description

skeleton

+5097
+1
.gitignore
··· 1 + _build
+18
dune-project
··· 1 + (lang dune 3.17) 2 + (name jmap) 3 + 4 + (source (github avsm/jmap)) 5 + (license ISC) 6 + (authors "Anil Madhavapeddy") 7 + (maintainers "anil@recoil.org") 8 + 9 + (generate_opam_files true) 10 + 11 + (package 12 + (name jmap) 13 + (synopsis "JMAP protocol") 14 + (description "This is all still a work in progress") 15 + (depends 16 + (ocaml (>= "5.2.0")) 17 + ezjsonm 18 + ptime))
+31
jmap.opam
··· 1 + # This file is generated by dune, edit dune-project instead 2 + opam-version: "2.0" 3 + synopsis: "JMAP protocol" 4 + description: "This is all still a work in progress" 5 + maintainer: ["anil@recoil.org"] 6 + authors: ["Anil Madhavapeddy"] 7 + license: "ISC" 8 + homepage: "https://github.com/avsm/jmap" 9 + bug-reports: "https://github.com/avsm/jmap/issues" 10 + depends: [ 11 + "dune" {>= "3.17"} 12 + "ocaml" {>= "5.2.0"} 13 + "ezjsonm" 14 + "ptime" 15 + "odoc" {with-doc} 16 + ] 17 + build: [ 18 + ["dune" "subst"] {dev} 19 + [ 20 + "dune" 21 + "build" 22 + "-p" 23 + name 24 + "-j" 25 + jobs 26 + "@install" 27 + "@runtest" {with-test} 28 + "@doc" {with-doc} 29 + ] 30 + ] 31 + dev-repo: "git+https://github.com/avsm/jmap.git"
+4
lib/dune
··· 1 + (library 2 + (name jmap) 3 + (public_name jmap) 4 + (libraries ezjsonm ptime))
lib/jmap.ml

This is a binary file and will not be displayed.

lib/jmap.mli

This is a binary file and will not be displayed.

+5043
spec/rfc8620.txt
··· 1 + 2 + 3 + 4 + 5 + 6 + 7 + Internet Engineering Task Force (IETF) N. Jenkins 8 + Request for Comments: 8620 Fastmail 9 + Category: Standards Track C. Newman 10 + ISSN: 2070-1721 Oracle 11 + July 2019 12 + 13 + 14 + The JSON Meta Application Protocol (JMAP) 15 + 16 + Abstract 17 + 18 + This document specifies a protocol for clients to efficiently query, 19 + fetch, and modify JSON-based data objects, with support for push 20 + notification of changes and fast resynchronisation and for out-of- 21 + band binary data upload/download. 22 + 23 + Status of This Memo 24 + 25 + This is an Internet Standards Track document. 26 + 27 + This document is a product of the Internet Engineering Task Force 28 + (IETF). It represents the consensus of the IETF community. It has 29 + received public review and has been approved for publication by the 30 + Internet Engineering Steering Group (IESG). Further information on 31 + Internet Standards is available in Section 2 of RFC 7841. 32 + 33 + Information about the current status of this document, any errata, 34 + and how to provide feedback on it may be obtained at 35 + https://www.rfc-editor.org/info/rfc8620. 36 + 37 + Copyright Notice 38 + 39 + Copyright (c) 2019 IETF Trust and the persons identified as the 40 + document authors. All rights reserved. 41 + 42 + This document is subject to BCP 78 and the IETF Trust's Legal 43 + Provisions Relating to IETF Documents 44 + (https://trustee.ietf.org/license-info) in effect on the date of 45 + publication of this document. Please review these documents 46 + carefully, as they describe your rights and restrictions with respect 47 + to this document. Code Components extracted from this document must 48 + include Simplified BSD License text as described in Section 4.e of 49 + the Trust Legal Provisions and are provided without warranty as 50 + described in the Simplified BSD License. 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + Jenkins & Newman Standards Track [Page 1] 59 + 60 + RFC 8620 JMAP July 2019 61 + 62 + 63 + Table of Contents 64 + 65 + 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 66 + 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4 67 + 1.2. The Id Data Type . . . . . . . . . . . . . . . . . . . . 6 68 + 1.3. The Int and UnsignedInt Data Types . . . . . . . . . . . 6 69 + 1.4. The Date and UTCDate Data Types . . . . . . . . . . . . . 7 70 + 1.5. JSON as the Data Encoding Format . . . . . . . . . . . . 7 71 + 1.6. Terminology . . . . . . . . . . . . . . . . . . . . . . . 7 72 + 1.6.1. User . . . . . . . . . . . . . . . . . . . . . . . . 7 73 + 1.6.2. Accounts . . . . . . . . . . . . . . . . . . . . . . 7 74 + 1.6.3. Data Types and Records . . . . . . . . . . . . . . . 8 75 + 1.7. The JMAP API Model . . . . . . . . . . . . . . . . . . . 8 76 + 1.8. Vendor-Specific Extensions . . . . . . . . . . . . . . . 9 77 + 2. The JMAP Session Resource . . . . . . . . . . . . . . . . . . 9 78 + 2.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 14 79 + 2.2. Service Autodiscovery . . . . . . . . . . . . . . . . . . 15 80 + 3. Structured Data Exchange . . . . . . . . . . . . . . . . . . 16 81 + 3.1. Making an API Request . . . . . . . . . . . . . . . . . . 16 82 + 3.2. The Invocation Data Type . . . . . . . . . . . . . . . . 16 83 + 3.3. The Request Object . . . . . . . . . . . . . . . . . . . 16 84 + 3.3.1. Example Request . . . . . . . . . . . . . . . . . . . 18 85 + 3.4. The Response Object . . . . . . . . . . . . . . . . . . . 18 86 + 3.4.1. Example Response . . . . . . . . . . . . . . . . . . 19 87 + 3.5. Omitting Arguments . . . . . . . . . . . . . . . . . . . 19 88 + 3.6. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 19 89 + 3.6.1. Request-Level Errors . . . . . . . . . . . . . . . . 20 90 + 3.6.2. Method-Level Errors . . . . . . . . . . . . . . . . . 21 91 + 3.7. References to Previous Method Results . . . . . . . . . . 22 92 + 3.8. Localisation of User-Visible Strings . . . . . . . . . . 27 93 + 3.9. Security . . . . . . . . . . . . . . . . . . . . . . . . 28 94 + 3.10. Concurrency . . . . . . . . . . . . . . . . . . . . . . . 28 95 + 4. The Core/echo Method . . . . . . . . . . . . . . . . . . . . 28 96 + 4.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 28 97 + 5. Standard Methods and Naming Convention . . . . . . . . . . . 29 98 + 5.1. /get . . . . . . . . . . . . . . . . . . . . . . . . . . 29 99 + 5.2. /changes . . . . . . . . . . . . . . . . . . . . . . . . 30 100 + 5.3. /set . . . . . . . . . . . . . . . . . . . . . . . . . . 34 101 + 5.4. /copy . . . . . . . . . . . . . . . . . . . . . . . . . . 40 102 + 5.5. /query . . . . . . . . . . . . . . . . . . . . . . . . . 42 103 + 5.6. /queryChanges . . . . . . . . . . . . . . . . . . . . . . 48 104 + 5.7. Examples . . . . . . . . . . . . . . . . . . . . . . . . 51 105 + 5.8. Proxy Considerations . . . . . . . . . . . . . . . . . . 58 106 + 6. Binary Data . . . . . . . . . . . . . . . . . . . . . . . . . 58 107 + 6.1. Uploading Binary Data . . . . . . . . . . . . . . . . . . 59 108 + 6.2. Downloading Binary Data . . . . . . . . . . . . . . . . . 60 109 + 6.3. Blob/copy . . . . . . . . . . . . . . . . . . . . . . . . 61 110 + 111 + 112 + 113 + 114 + Jenkins & Newman Standards Track [Page 2] 115 + 116 + RFC 8620 JMAP July 2019 117 + 118 + 119 + 7. Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 120 + 7.1. The StateChange Object . . . . . . . . . . . . . . . . . 63 121 + 7.1.1. Example . . . . . . . . . . . . . . . . . . . . . . . 64 122 + 7.2. PushSubscription . . . . . . . . . . . . . . . . . . . . 64 123 + 7.2.1. PushSubscription/get . . . . . . . . . . . . . . . . 67 124 + 7.2.2. PushSubscription/set . . . . . . . . . . . . . . . . 68 125 + 7.2.3. Example . . . . . . . . . . . . . . . . . . . . . . . 69 126 + 7.3. Event Source . . . . . . . . . . . . . . . . . . . . . . 71 127 + 8. Security Considerations . . . . . . . . . . . . . . . . . . . 73 128 + 8.1. Transport Confidentiality . . . . . . . . . . . . . . . . 73 129 + 8.2. Authentication Scheme . . . . . . . . . . . . . . . . . . 73 130 + 8.3. Service Autodiscovery . . . . . . . . . . . . . . . . . . 73 131 + 8.4. JSON Parsing . . . . . . . . . . . . . . . . . . . . . . 74 132 + 8.5. Denial of Service . . . . . . . . . . . . . . . . . . . . 74 133 + 8.6. Connection to Unknown Push Server . . . . . . . . . . . . 74 134 + 8.7. Push Encryption . . . . . . . . . . . . . . . . . . . . . 75 135 + 8.8. Traffic Analysis . . . . . . . . . . . . . . . . . . . . 76 136 + 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 76 137 + 9.1. Assignment of jmap Service Name . . . . . . . . . . . . . 76 138 + 9.2. Registration of Well-Known URI Suffix for JMAP . . . . . 76 139 + 9.3. Registration of the jmap URN Sub-namespace . . . . . . . 77 140 + 9.4. Creation of "JMAP Capabilities" Registry . . . . . . . . 77 141 + 9.4.1. Preliminary Community Review . . . . . . . . . . . . 77 142 + 9.4.2. Submit Request to IANA . . . . . . . . . . . . . . . 78 143 + 9.4.3. Designated Expert Review . . . . . . . . . . . . . . 78 144 + 9.4.4. Change Procedures . . . . . . . . . . . . . . . . . . 78 145 + 9.4.5. JMAP Capabilities Registry Template . . . . . . . . . 79 146 + 9.4.6. Initial Registration for JMAP Core . . . . . . . . . 79 147 + 9.4.7. Registration for JMAP Error Placeholder in JMAP 148 + Capabilities Registry . . . . . . . . . . . . . . . . 80 149 + 9.5. Creation of "JMAP Error Codes" Registry . . . . . . . . . 80 150 + 9.5.1. Expert Review . . . . . . . . . . . . . . . . . . . . 80 151 + 9.5.2. JMAP Error Codes Registry Template . . . . . . . . . 81 152 + 9.5.3. Initial Contents for the JMAP Error Codes Registry . 81 153 + 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 86 154 + 10.1. Normative References . . . . . . . . . . . . . . . . . . 86 155 + 10.2. Informative References . . . . . . . . . . . . . . . . . 89 156 + Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 90 157 + 158 + 159 + 160 + 161 + 162 + 163 + 164 + 165 + 166 + 167 + 168 + 169 + 170 + Jenkins & Newman Standards Track [Page 3] 171 + 172 + RFC 8620 JMAP July 2019 173 + 174 + 175 + 1. Introduction 176 + 177 + The JSON Meta Application Protocol (JMAP) is used for synchronising 178 + data, such as mail, calendars, or contacts, between a client and a 179 + server. It is optimised for mobile and web environments and aims to 180 + provide a consistent interface to different data types. 181 + 182 + This specification is for the generic mechanism of data 183 + synchronisation. Further specifications define the data models for 184 + different data types that may be synchronised via JMAP. 185 + 186 + JMAP is designed to make efficient use of limited network resources. 187 + Multiple API calls may be batched in a single request to the server, 188 + reducing round trips and improving battery life on mobile devices. 189 + Push connections remove the need for polling, and an efficient delta 190 + update mechanism ensures a minimum amount of data is transferred. 191 + 192 + JMAP is designed to be horizontally scalable to a very large number 193 + of users. This is facilitated by separate endpoints for users after 194 + login, the separation of binary and structured data, and a data model 195 + for sharing that does not allow data dependencies between accounts. 196 + 197 + 1.1. Notational Conventions 198 + 199 + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 200 + "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 201 + "OPTIONAL" in this document are to be interpreted as described in 202 + BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all 203 + capitals, as shown here. 204 + 205 + The underlying format used for this specification is JSON. 206 + Consequently, the terms "object" and "array" as well as the four 207 + primitive types (strings, numbers, booleans, and null) are to be 208 + interpreted as described in Section 1 of [RFC8259]. Unless otherwise 209 + noted, all the property names and values are case sensitive. 210 + 211 + Some examples in this document contain "partial" JSON documents used 212 + for illustrative purposes. In these examples, three periods "..." 213 + are used to indicate a portion of the document that has been removed 214 + for compactness. 215 + 216 + For compatibility with publishing requirements, line breaks have been 217 + inserted inside long JSON strings, with the following continuation 218 + lines indented. To form the valid JSON example, any line breaks 219 + inside a string must be replaced with a space and any other white 220 + space after the line break removed. 221 + 222 + 223 + 224 + 225 + 226 + Jenkins & Newman Standards Track [Page 4] 227 + 228 + RFC 8620 JMAP July 2019 229 + 230 + 231 + Unless otherwise specified, examples of API exchanges only show the 232 + methodCalls array of the Request object or the methodResponses array 233 + of the Response object. For compactness, the rest of the Request/ 234 + Response object is omitted. 235 + 236 + Type signatures are given for all JSON values in this document. The 237 + following conventions are used: 238 + 239 + o "*" - The type is undefined (the value could be any type, although 240 + permitted values may be constrained by the context of this value). 241 + 242 + o "String" - The JSON string type. 243 + 244 + o "Number" - The JSON number type. 245 + 246 + o "Boolean" - The JSON boolean type. 247 + 248 + o "A[B]" - A JSON object where the keys are all of type "A", and the 249 + values are all of type "B". 250 + 251 + o "A[]" - An array of values of type "A". 252 + 253 + o "A|B" - The value is either of type "A" or of type "B". 254 + 255 + Other types may also be given, with their representation defined 256 + elsewhere in this document. 257 + 258 + Object properties may also have a set of attributes defined along 259 + with the type signature. These have the following meanings: 260 + 261 + o "server-set" -- Only the server can set the value for this 262 + property. The client MUST NOT send this property when creating a 263 + new object of this type. 264 + 265 + o "immutable" -- The value MUST NOT change after the object is 266 + created. 267 + 268 + o "default" -- (This is followed by a JSON value). The value that 269 + will be used for this property if it is omitted in an argument or 270 + when creating a new object of this type. 271 + 272 + 273 + 274 + 275 + 276 + 277 + 278 + 279 + 280 + 281 + 282 + Jenkins & Newman Standards Track [Page 5] 283 + 284 + RFC 8620 JMAP July 2019 285 + 286 + 287 + 1.2. The Id Data Type 288 + 289 + All record ids are assigned by the server and are immutable. 290 + 291 + Where "Id" is given as a data type, it means a "String" of at least 1 292 + and a maximum of 255 octets in size, and it MUST only contain 293 + characters from the "URL and Filename Safe" base64 alphabet, as 294 + defined in Section 5 of [RFC4648], excluding the pad character ("="). 295 + This means the allowed characters are the ASCII alphanumeric 296 + characters ("A-Za-z0-9"), hyphen ("-"), and underscore ("_"). 297 + 298 + These characters are safe to use in almost any context (e.g., 299 + filesystems, URIs, and IMAP atoms). For maximum safety, servers 300 + SHOULD also follow defensive allocation strategies to avoid creating 301 + risks where glob completion or data type detection may be present 302 + (e.g., on filesystems or in spreadsheets). In particular, it is wise 303 + to avoid: 304 + 305 + o Ids starting with a dash 306 + 307 + o Ids starting with digits 308 + 309 + o Ids that contain only digits 310 + 311 + o Ids that differ only by ASCII case (for example, A vs. a) 312 + 313 + o the specific sequence of three characters "NIL" (because this 314 + sequence can be confused with the IMAP protocol expression of the 315 + null value) 316 + 317 + A good solution to these issues is to prefix every id with a single 318 + alphabetical character. 319 + 320 + 1.3. The Int and UnsignedInt Data Types 321 + 322 + Where "Int" is given as a data type, it means an integer in the range 323 + -2^53+1 <= value <= 2^53-1, the safe range for integers stored in a 324 + floating-point double, represented as a JSON "Number". 325 + 326 + Where "UnsignedInt" is given as a data type, it means an "Int" where 327 + the value MUST be in the range 0 <= value <= 2^53-1. 328 + 329 + 330 + 331 + 332 + 333 + 334 + 335 + 336 + 337 + 338 + Jenkins & Newman Standards Track [Page 6] 339 + 340 + RFC 8620 JMAP July 2019 341 + 342 + 343 + 1.4. The Date and UTCDate Data Types 344 + 345 + Where "Date" is given as a type, it means a string in "date-time" 346 + format [RFC3339]. To ensure a normalised form, the "time-secfrac" 347 + MUST always be omitted if zero, and any letters in the string (e.g., 348 + "T" and "Z") MUST be uppercase. For example, 349 + "2014-10-30T14:12:00+08:00". 350 + 351 + Where "UTCDate" is given as a type, it means a "Date" where the 352 + "time-offset" component MUST be "Z" (i.e., it must be in UTC time). 353 + For example, "2014-10-30T06:12:00Z". 354 + 355 + 1.5. JSON as the Data Encoding Format 356 + 357 + JSON is a text-based data interchange format as specified in 358 + [RFC8259]. The Internet JSON (I-JSON) format defined in [RFC7493] is 359 + a strict subset of this, adding restrictions to avoid potentially 360 + confusing scenarios (for example, it mandates that an object MUST NOT 361 + have two members with the same name). 362 + 363 + All data sent from the client to the server or from the server to the 364 + client (except binary file upload/download) MUST be valid I-JSON 365 + according to the RFC and is therefore case sensitive and encoded in 366 + UTF-8 [RFC3629]. 367 + 368 + 1.6. Terminology 369 + 370 + 1.6.1. User 371 + 372 + A user is a person accessing data via JMAP. A user has a set of 373 + permissions determining the data that they can see. 374 + 375 + 1.6.2. Accounts 376 + 377 + An account is a collection of data. A single account may contain an 378 + arbitrary set of data types, for example, a collection of mail, 379 + contacts, and calendars. Most JMAP methods take a mandatory 380 + "accountId" argument that specifies on which account the operations 381 + are to take place. 382 + 383 + An account is not the same as a user, although it is common for a 384 + primary account to directly belong to the user. For example, you may 385 + have an account that contains data for a group or business, to which 386 + multiple users have access. 387 + 388 + 389 + 390 + 391 + 392 + 393 + 394 + Jenkins & Newman Standards Track [Page 7] 395 + 396 + RFC 8620 JMAP July 2019 397 + 398 + 399 + A single set of credentials may provide access to multiple accounts, 400 + for example, if another user is sharing their work calendar with the 401 + authenticated user or if there is a group mailbox for a support-desk 402 + inbox. 403 + 404 + In the event of a severe internal error, a server may have to 405 + reallocate ids or do something else that violates standard JMAP data 406 + constraints for an account. In this situation, the data on the 407 + server is no longer compatible with cached data the client may have 408 + from before. The server MUST treat this as though the account has 409 + been deleted and then recreated with a new account id. Clients will 410 + then be forced to throw away any data with the old account id and 411 + refetch all data from scratch. 412 + 413 + 1.6.3. Data Types and Records 414 + 415 + JMAP provides a uniform interface for creating, retrieving, updating, 416 + and deleting various types of objects. A "data type" is a collection 417 + of named, typed properties, just like the schema for a database 418 + table. Each instance of a data type is called a "record". 419 + 420 + The id of a record is immutable and assigned by the server. The id 421 + MUST be unique among all records of the *same type* within the *same 422 + account*. Ids may clash across accounts or for two records of 423 + different types within the same account. 424 + 425 + 1.7. The JMAP API Model 426 + 427 + JMAP uses HTTP [RFC7230] to expose API, push, upload, and download 428 + resources. All HTTP requests MUST use the "https://" scheme (HTTP 429 + over TLS [RFC2818]). All HTTP requests MUST be authenticated. 430 + 431 + An authenticated client can fetch the user's Session object with 432 + details about the data and capabilities the server can provide as 433 + shown in Section 2. The client may then exchange data with the 434 + server in the following ways: 435 + 436 + 1. The client may make an API request to the server to get or set 437 + structured data. This request consists of an ordered series of 438 + method calls. These are processed by the server, which then 439 + returns an ordered series of responses. This is described in 440 + Sections 3, 4, and 5. 441 + 442 + 2. The client may download or upload binary files from/to the 443 + server. This is detailed in Section 6. 444 + 445 + 3. The client may connect to a push channel on the server, to be 446 + notified when data has changed. This is explained in Section 7. 447 + 448 + 449 + 450 + Jenkins & Newman Standards Track [Page 8] 451 + 452 + RFC 8620 JMAP July 2019 453 + 454 + 455 + 1.8. Vendor-Specific Extensions 456 + 457 + Individual services will have custom features they wish to expose 458 + over JMAP. This may take the form of extra data types and/or methods 459 + not in the spec, extra arguments to JMAP methods, or extra properties 460 + on existing data types (which may also appear in arguments to methods 461 + that take property names). 462 + 463 + The server can advertise custom extensions it supports by including 464 + the identifiers in the capabilities object. Identifiers for vendor 465 + extensions MUST be a URL belonging to a domain owned by the vendor, 466 + to avoid conflict. The URL SHOULD resolve to documentation for the 467 + changes the extension makes. 468 + 469 + The client MUST opt in to use an extension by passing the appropriate 470 + capability identifier in the "using" array of the Request object, as 471 + described in Section 3.3. The server MUST only follow the 472 + specifications that are opted into and behave as though it does not 473 + implement anything else when processing a request. This is to ensure 474 + compatibility with clients that don't know about a specific custom 475 + extension and for compatibility with future versions of JMAP. 476 + 477 + 2. The JMAP Session Resource 478 + 479 + You need two things to connect to a JMAP server: 480 + 481 + 1. The URL for the JMAP Session resource. This may be requested 482 + directly from the user or discovered automatically based on a 483 + username domain (see Section 2.2 below). 484 + 485 + 2. Credentials to authenticate with. How to obtain credentials is 486 + out of scope for this document. 487 + 488 + A successful authenticated GET request to the JMAP Session resource 489 + MUST return a JSON-encoded *Session* object, giving details about the 490 + data and capabilities the server can provide to the client given 491 + those credentials. It has the following properties: 492 + 493 + o capabilities: "String[Object]" 494 + 495 + An object specifying the capabilities of this server. Each key is 496 + a URI for a capability supported by the server. The value for 497 + each of these keys is an object with further information about the 498 + server's capabilities in relation to that capability. 499 + 500 + The client MUST ignore any properties it does not understand. 501 + 502 + 503 + 504 + 505 + 506 + Jenkins & Newman Standards Track [Page 9] 507 + 508 + RFC 8620 JMAP July 2019 509 + 510 + 511 + The capabilities object MUST include a property called 512 + "urn:ietf:params:jmap:core". The value of this property is an 513 + object that MUST contain the following information on server 514 + capabilities (suggested minimum values for limits are supplied 515 + that allow clients to make efficient use of the network): 516 + 517 + * maxSizeUpload: "UnsignedInt" 518 + 519 + The maximum file size, in octets, that the server will accept 520 + for a single file upload (for any purpose). Suggested minimum: 521 + 50,000,000. 522 + 523 + * maxConcurrentUpload: "UnsignedInt" 524 + 525 + The maximum number of concurrent requests the server will 526 + accept to the upload endpoint. Suggested minimum: 4. 527 + 528 + * maxSizeRequest: "UnsignedInt" 529 + 530 + The maximum size, in octets, that the server will accept for a 531 + single request to the API endpoint. Suggested minimum: 532 + 10,000,000. 533 + 534 + * maxConcurrentRequests: "UnsignedInt" 535 + 536 + The maximum number of concurrent requests the server will 537 + accept to the API endpoint. Suggested minimum: 4. 538 + 539 + * maxCallsInRequest: "UnsignedInt" 540 + 541 + The maximum number of method calls the server will accept in a 542 + single request to the API endpoint. Suggested minimum: 16. 543 + 544 + * maxObjectsInGet: "UnsignedInt" 545 + 546 + The maximum number of objects that the client may request in a 547 + single /get type method call. Suggested minimum: 500. 548 + 549 + * maxObjectsInSet: "UnsignedInt" 550 + 551 + The maximum number of objects the client may send to create, 552 + update, or destroy in a single /set type method call. This is 553 + the combined total, e.g., if the maximum is 10, you could not 554 + create 7 objects and destroy 6, as this would be 13 actions, 555 + which exceeds the limit. Suggested minimum: 500. 556 + 557 + 558 + 559 + 560 + 561 + 562 + Jenkins & Newman Standards Track [Page 10] 563 + 564 + RFC 8620 JMAP July 2019 565 + 566 + 567 + * collationAlgorithms: "String[]" 568 + 569 + A list of identifiers for algorithms registered in the 570 + collation registry, as defined in [RFC4790], that the server 571 + supports for sorting when querying records. 572 + 573 + Specifications for future capabilities will define their own 574 + properties on the capabilities object. 575 + 576 + Servers MAY advertise vendor-specific JMAP extensions, as 577 + described in Section 1.8. To avoid conflict, an identifier for a 578 + vendor-specific extension MUST be a URL with a domain owned by the 579 + vendor. Clients MUST opt in to any capability it wishes to use 580 + (see Section 3.3). 581 + 582 + o accounts: "Id[Account]" 583 + 584 + A map of an account id to an Account object for each account (see 585 + Section 1.6.2) the user has access to. An *Account* object has 586 + the following properties: 587 + 588 + * name: "String" 589 + 590 + A user-friendly string to show when presenting content from 591 + this account, e.g., the email address representing the owner of 592 + the account. 593 + 594 + * isPersonal: "Boolean" 595 + 596 + This is true if the account belongs to the authenticated user 597 + rather than a group account or a personal account of another 598 + user that has been shared with them. 599 + 600 + * isReadOnly: "Boolean" 601 + 602 + This is true if the entire account is read-only. 603 + 604 + * accountCapabilities: "String[Object]" 605 + 606 + The set of capability URIs for the methods supported in this 607 + account. Each key is a URI for a capability that has methods 608 + you can use with this account. The value for each of these 609 + keys is an object with further information about the account's 610 + permissions and restrictions with respect to this capability, 611 + as defined in the capability's specification. 612 + 613 + The client MUST ignore any properties it does not understand. 614 + 615 + 616 + 617 + 618 + Jenkins & Newman Standards Track [Page 11] 619 + 620 + RFC 8620 JMAP July 2019 621 + 622 + 623 + The server advertises the full list of capabilities it supports 624 + in the capabilities object, as defined above. If the 625 + capability defines new methods, the server MUST include it in 626 + the accountCapabilities object if the user may use those 627 + methods with this account. It MUST NOT include it in the 628 + accountCapabilities object if the user cannot use those methods 629 + with this account. 630 + 631 + For example, you may have access to your own account with mail, 632 + calendars, and contacts data and also a shared account that 633 + only has contacts data (a business address book, for example). 634 + In this case, the accountCapabilities property on the first 635 + account would include something like 636 + "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:calendars", 637 + and "urn:ietf:params:jmap:contacts", while the second account 638 + would just have the last of these. 639 + 640 + Attempts to use the methods defined in a capability with one of 641 + the accounts that does not support that capability are rejected 642 + with an "accountNotSupportedByMethod" error (see "Method-Level 643 + Errors", Section 3.6.2). 644 + 645 + o primaryAccounts: "String[Id]" 646 + 647 + A map of capability URIs (as found in accountCapabilities) to the 648 + account id that is considered to be the user's main or default 649 + account for data pertaining to that capability. If no account 650 + being returned belongs to the user, or in any other way there is 651 + no appropriate way to determine a default account, there MAY be no 652 + entry for a particular URI, even though that capability is 653 + supported by the server (and in the capabilities object). 654 + "urn:ietf:params:jmap:core" SHOULD NOT be present. 655 + 656 + o username: "String" 657 + 658 + The username associated with the given credentials, or the empty 659 + string if none. 660 + 661 + o apiUrl: "String" 662 + 663 + The URL to use for JMAP API requests. 664 + 665 + 666 + 667 + 668 + 669 + 670 + 671 + 672 + 673 + 674 + Jenkins & Newman Standards Track [Page 12] 675 + 676 + RFC 8620 JMAP July 2019 677 + 678 + 679 + o downloadUrl: "String" 680 + 681 + The URL endpoint to use when downloading files, in URI Template 682 + (level 1) format [RFC6570]. The URL MUST contain variables called 683 + "accountId", "blobId", "type", and "name". The use of these 684 + variables is described in Section 6.2. Due to potential encoding 685 + issues with slashes in content types, it is RECOMMENDED to put the 686 + "type" variable in the query section of the URL. 687 + 688 + o uploadUrl: "String" 689 + 690 + The URL endpoint to use when uploading files, in URI Template 691 + (level 1) format [RFC6570]. The URL MUST contain a variable 692 + called "accountId". The use of this variable is described in 693 + Section 6.1. 694 + 695 + o eventSourceUrl: "String" 696 + 697 + The URL to connect to for push events, as described in 698 + Section 7.3, in URI Template (level 1) format [RFC6570]. The URL 699 + MUST contain variables called "types", "closeafter", and "ping". 700 + The use of these variables is described in Section 7.3. 701 + 702 + o state: "String" 703 + 704 + A (preferably short) string representing the state of this object 705 + on the server. If the value of any other property on the Session 706 + object changes, this string will change. The current value is 707 + also returned on the API Response object (see Section 3.4), 708 + allowing clients to quickly determine if the session information 709 + has changed (e.g., an account has been added or removed), so they 710 + need to refetch the object. 711 + 712 + To ensure future compatibility, other properties MAY be included on 713 + the Session object. Clients MUST ignore any properties they are not 714 + expecting. 715 + 716 + Implementors must take care to avoid inappropriate caching of the 717 + Session object at the HTTP layer. Since the client should only 718 + refetch when it detects there is a change (via the sessionState 719 + property of an API response), it is RECOMMENDED to disable HTTP 720 + caching altogether, for example, by setting "Cache-Control: no-cache, 721 + no-store, must-revalidate" on the response. 722 + 723 + 724 + 725 + 726 + 727 + 728 + 729 + 730 + Jenkins & Newman Standards Track [Page 13] 731 + 732 + RFC 8620 JMAP July 2019 733 + 734 + 735 + 2.1. Example 736 + 737 + In the following example Session object, the user has access to their 738 + own mail and contacts via JMAP, as well as read-only access to shared 739 + mail from another user. The server is advertising a custom 740 + "https://example.com/apis/foobar" capability. 741 + 742 + { 743 + "capabilities": { 744 + "urn:ietf:params:jmap:core": { 745 + "maxSizeUpload": 50000000, 746 + "maxConcurrentUpload": 8, 747 + "maxSizeRequest": 10000000, 748 + "maxConcurrentRequest": 8, 749 + "maxCallsInRequest": 32, 750 + "maxObjectsInGet": 256, 751 + "maxObjectsInSet": 128, 752 + "collationAlgorithms": [ 753 + "i;ascii-numeric", 754 + "i;ascii-casemap", 755 + "i;unicode-casemap" 756 + ] 757 + }, 758 + "urn:ietf:params:jmap:mail": {} 759 + "urn:ietf:params:jmap:contacts": {}, 760 + "https://example.com/apis/foobar": { 761 + "maxFoosFinangled": 42 762 + } 763 + }, 764 + "accounts": { 765 + "A13824": { 766 + "name": "john@example.com", 767 + "isPersonal": true, 768 + "isReadOnly": false, 769 + "accountCapabilities": { 770 + "urn:ietf:params:jmap:mail": { 771 + "maxMailboxesPerEmail": null, 772 + "maxMailboxDepth": 10, 773 + ... 774 + }, 775 + "urn:ietf:params:jmap:contacts": { 776 + ... 777 + } 778 + } 779 + }, 780 + 781 + 782 + 783 + 784 + 785 + 786 + Jenkins & Newman Standards Track [Page 14] 787 + 788 + RFC 8620 JMAP July 2019 789 + 790 + 791 + "A97813": { 792 + "name": "jane@example.com", 793 + "isPersonal": false, 794 + "isReadOnly": true, 795 + "accountCapabilities": { 796 + "urn:ietf:params:jmap:mail": { 797 + "maxMailboxesPerEmail": 1, 798 + "maxMailboxDepth": 10, 799 + ... 800 + } 801 + } 802 + } 803 + }, 804 + "primaryAccounts": { 805 + "urn:ietf:params:jmap:mail": "A13824", 806 + "urn:ietf:params:jmap:contacts": "A13824" 807 + }, 808 + "username": "john@example.com", 809 + "apiUrl": "https://jmap.example.com/api/", 810 + "downloadUrl": "https://jmap.example.com 811 + /download/{accountId}/{blobId}/{name}?accept={type}", 812 + "uploadUrl": "https://jmap.example.com/upload/{accountId}/", 813 + "eventSourceUrl": "https://jmap.example.com 814 + /eventsource/?types={types}&closeafter={closeafter}&ping={ping}", 815 + "state": "75128aab4b1b" 816 + } 817 + 818 + 2.2. Service Autodiscovery 819 + 820 + There are two standardised autodiscovery methods in use for Internet 821 + protocols: 822 + 823 + o DNS SRV (see [RFC2782], [RFC6186], and [RFC6764]) 824 + 825 + o .well-known/servicename (see [RFC8615]) 826 + 827 + A JMAP-supporting host for the domain "example.com" SHOULD publish a 828 + SRV record "_jmap._tcp.example.com" that gives a hostname and port 829 + (usually port "443"). The JMAP Session resource is then 830 + "https://${hostname}[:${port}]/.well-known/jmap" (following any 831 + redirects). 832 + 833 + If the client has a username in the form of an email address, it MAY 834 + use the domain portion of this to attempt autodiscovery of the JMAP 835 + server. 836 + 837 + 838 + 839 + 840 + 841 + 842 + Jenkins & Newman Standards Track [Page 15] 843 + 844 + RFC 8620 JMAP July 2019 845 + 846 + 847 + 3. Structured Data Exchange 848 + 849 + The client may make an API request to the server to get or set 850 + structured data. This request consists of an ordered series of 851 + method calls. These are processed by the server, which then returns 852 + an ordered series of responses. 853 + 854 + 3.1. Making an API Request 855 + 856 + To make an API request, the client makes an authenticated POST 857 + request to the API resource, which is defined by the "apiUrl" 858 + property in the Session object (see Section 2). 859 + 860 + The request MUST be of type "application/json" and consist of a 861 + single JSON-encoded "Request" object, as defined in Section 3.3. If 862 + successful, the response MUST also be of type "application/json" and 863 + consist of a single "Response" object, as defined in Section 3.4. 864 + 865 + 3.2. The Invocation Data Type 866 + 867 + Method calls and responses are represented by the *Invocation* data 868 + type. This is a tuple, represented as a JSON array containing three 869 + elements: 870 + 871 + 1. A "String" *name* of the method to call or of the response. 872 + 873 + 2. A "String[*]" object containing named *arguments* for that method 874 + or response. 875 + 876 + 3. A "String" *method call id*: an arbitrary string from the client 877 + to be echoed back with the responses emitted by that method call 878 + (a method may return 1 or more responses, as it may make implicit 879 + calls to other methods; all responses initiated by this method 880 + call get the same method call id in the response). 881 + 882 + 3.3. The Request Object 883 + 884 + A *Request* object has the following properties: 885 + 886 + o using: "String[]" 887 + 888 + The set of capabilities the client wishes to use. The client MAY 889 + include capability identifiers even if the method calls it makes 890 + do not utilise those capabilities. The server advertises the set 891 + of specifications it supports in the Session object (see 892 + Section 2), as keys on the "capabilities" property. 893 + 894 + 895 + 896 + 897 + 898 + Jenkins & Newman Standards Track [Page 16] 899 + 900 + RFC 8620 JMAP July 2019 901 + 902 + 903 + o methodCalls: "Invocation[]" 904 + 905 + An array of method calls to process on the server. The method 906 + calls MUST be processed sequentially, in order. 907 + 908 + o createdIds: "Id[Id]" (optional) 909 + 910 + A map of a (client-specified) creation id to the id the server 911 + assigned when a record was successfully created. 912 + 913 + As described later in this specification, some records may have a 914 + property that contains the id of another record. To allow more 915 + efficient network usage, you can set this property to reference a 916 + record created earlier in the same API request. Since the real id 917 + is unknown when the request is created, the client can instead 918 + specify the creation id it assigned, prefixed with a "#" (see 919 + Section 5.3 for more details). 920 + 921 + As the server processes API requests, any time it successfully 922 + creates a new record, it adds the creation id to this map (see the 923 + "create" argument to /set in Section 5.3), with the server- 924 + assigned real id as the value. If it comes across a reference to 925 + a creation id in a create/update, it looks it up in the map and 926 + replaces the reference with the real id, if found. 927 + 928 + The client can pass an initial value for this map as the 929 + "createdIds" property of the Request object. This may be an empty 930 + object. If given in the request, the response will also include a 931 + createdIds property. This allows proxy servers to easily split a 932 + JMAP request into multiple JMAP requests to send to different 933 + servers. For example, it could send the first two method calls to 934 + server A, then the third to server B, before sending the fourth to 935 + server A again. By passing the createdIds of the previous 936 + response to the next request, it can ensure all of these still 937 + resolve. See Section 5.8 for further discussion of proxy 938 + considerations. 939 + 940 + Future specifications MAY add further properties to the Request 941 + object to extend the semantics. To ensure forwards compatibility, a 942 + server MUST ignore any other properties it does not understand on the 943 + JMAP Request object. 944 + 945 + 946 + 947 + 948 + 949 + 950 + 951 + 952 + 953 + 954 + Jenkins & Newman Standards Track [Page 17] 955 + 956 + RFC 8620 JMAP July 2019 957 + 958 + 959 + 3.3.1. Example Request 960 + 961 + { 962 + "using": [ "urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail" ], 963 + "methodCalls": [ 964 + [ "method1", { 965 + "arg1": "arg1data", 966 + "arg2": "arg2data" 967 + }, "c1" ], 968 + [ "method2", { 969 + "arg1": "arg1data" 970 + }, "c2" ], 971 + [ "method3", {}, "c3" ] 972 + ] 973 + } 974 + 975 + 3.4. The Response Object 976 + 977 + A *Response* object has the following properties: 978 + 979 + o methodResponses: "Invocation[]" 980 + 981 + An array of responses, in the same format as the "methodCalls" on 982 + the Request object. The output of the methods MUST be added to 983 + the "methodResponses" array in the same order that the methods are 984 + processed. 985 + 986 + o createdIds: "Id[Id]" (optional; only returned if given in the 987 + request) 988 + 989 + A map of a (client-specified) creation id to the id the server 990 + assigned when a record was successfully created. This MUST 991 + include all creation ids passed in the original createdIds 992 + parameter of the Request object, as well as any additional ones 993 + added for newly created records. 994 + 995 + o sessionState: "String" 996 + 997 + The current value of the "state" string on the Session object, as 998 + described in Section 2. Clients may use this to detect if this 999 + object has changed and needs to be refetched. 1000 + 1001 + Unless otherwise specified, if the method call completed 1002 + successfully, its response name is the same as the method name in the 1003 + request. 1004 + 1005 + 1006 + 1007 + 1008 + 1009 + 1010 + Jenkins & Newman Standards Track [Page 18] 1011 + 1012 + RFC 8620 JMAP July 2019 1013 + 1014 + 1015 + 3.4.1. Example Response 1016 + 1017 + { 1018 + "methodResponses": [ 1019 + [ "method1", { 1020 + "arg1": 3, 1021 + "arg2": "foo" 1022 + }, "c1" ], 1023 + [ "method2", { 1024 + "isBlah": true 1025 + }, "c2" ], 1026 + [ "anotherResponseFromMethod2", { 1027 + "data": 10, 1028 + "yetmoredata": "Hello" 1029 + }, "c2"], 1030 + [ "error", { 1031 + "type":"unknownMethod" 1032 + }, "c3" ] 1033 + ], 1034 + "sessionState": "75128aab4b1b" 1035 + } 1036 + 1037 + 3.5. Omitting Arguments 1038 + 1039 + An argument to a method may be specified to have a default value. If 1040 + omitted by the client, the server MUST treat the method call the same 1041 + as if the default value had been specified. Similarly, the server 1042 + MAY omit any argument in a response that has the default value. 1043 + 1044 + Unless otherwise specified in a method description, null is the 1045 + default value for any argument in a request or response where this is 1046 + allowed by the type signature. Other arguments may only be omitted 1047 + if an explicit default value is defined in the method description. 1048 + 1049 + 3.6. Errors 1050 + 1051 + There are three different levels of granularity at which an error may 1052 + be returned in JMAP. 1053 + 1054 + When an API request is made, the request as a whole may be rejected 1055 + due to rate limiting, malformed JSON, request for an unknown 1056 + capability, etc. In this case, the entire request is rejected with 1057 + an appropriate HTTP error response code and an additional JSON body 1058 + with more detail for the client. 1059 + 1060 + Provided the request itself is syntactically valid (the JSON is valid 1061 + and when decoded, it matches the type signature of a Request object), 1062 + the methods within it are executed sequentially by the server. Each 1063 + 1064 + 1065 + 1066 + Jenkins & Newman Standards Track [Page 19] 1067 + 1068 + RFC 8620 JMAP July 2019 1069 + 1070 + 1071 + method may individually fail, for example, if invalid arguments are 1072 + given or an unknown method name is called. 1073 + 1074 + Finally, methods that make changes to the server state often act upon 1075 + a number of different records within a single call. Each record 1076 + change may be separately rejected with a SetError, as described in 1077 + Section 5.3. 1078 + 1079 + 3.6.1. Request-Level Errors 1080 + 1081 + When an HTTP error response is returned to the client, the server 1082 + SHOULD return a JSON "problem details" object as the response body, 1083 + as per [RFC7807]. 1084 + 1085 + The following problem types are defined: 1086 + 1087 + o "urn:ietf:params:jmap:error:unknownCapability" 1088 + The client included a capability in the "using" property of the 1089 + request that the server does not support. 1090 + 1091 + o "urn:ietf:params:jmap:error:notJSON" 1092 + The content type of the request was not "application/json" or the 1093 + request did not parse as I-JSON. 1094 + 1095 + o "urn:ietf:params:jmap:error:notRequest" 1096 + The request parsed as JSON but did not match the type signature of 1097 + the Request object. 1098 + 1099 + o "urn:ietf:params:jmap:error:limit" 1100 + The request was not processed as it would have exceeded one of the 1101 + request limits defined on the capability object, such as 1102 + maxSizeRequest, maxCallsInRequest, or maxConcurrentRequests. A 1103 + "limit" property MUST also be present on the "problem details" 1104 + object, containing the name of the limit being applied. 1105 + 1106 + 3.6.1.1. Example 1107 + 1108 + { 1109 + "type": "urn:ietf:params:jmap:error:unknownCapability", 1110 + "status": 400, 1111 + "detail": "The Request object used capability 1112 + 'https://example.com/apis/foobar', which is not supported 1113 + by this server." 1114 + } 1115 + 1116 + 1117 + 1118 + 1119 + 1120 + 1121 + 1122 + Jenkins & Newman Standards Track [Page 20] 1123 + 1124 + RFC 8620 JMAP July 2019 1125 + 1126 + 1127 + Another example: 1128 + 1129 + { 1130 + "type": "urn:ietf:params:jmap:error:limit", 1131 + "limit": "maxSizeRequest", 1132 + "status": 400, 1133 + "detail": "The request is larger than the server is willing to 1134 + process." 1135 + } 1136 + 1137 + 3.6.2. Method-Level Errors 1138 + 1139 + If a method encounters an error, the appropriate "error" response 1140 + MUST be inserted at the current point in the "methodResponses" array 1141 + and, unless otherwise specified, further processing MUST NOT happen 1142 + within that method call. 1143 + 1144 + Any further method calls in the request MUST then be processed as 1145 + normal. Errors at the method level MUST NOT generate an HTTP-level 1146 + error. 1147 + 1148 + An "error" response looks like this: 1149 + 1150 + [ "error", { 1151 + "type": "unknownMethod" 1152 + }, "call-id" ] 1153 + 1154 + The response name is "error", and it MUST have a type property. 1155 + Other properties may be present with further information; these are 1156 + detailed in the error type descriptions where appropriate. 1157 + 1158 + With the exception of when the "serverPartialFail" error is returned, 1159 + the externally visible state of the server MUST NOT have changed if 1160 + an error is returned at the method level. 1161 + 1162 + The following error types are defined, which may be returned for any 1163 + method call where appropriate: 1164 + 1165 + "serverUnavailable": Some internal server resource was temporarily 1166 + unavailable. Attempting the same operation later (perhaps after a 1167 + backoff with a random factor) may succeed. 1168 + 1169 + "serverFail": An unexpected or unknown error occurred during the 1170 + processing of the call. A "description" property should provide more 1171 + details about the error. The method call made no changes to the 1172 + server's state. Attempting the same operation again is expected to 1173 + fail again. Contacting the service administrator is likely necessary 1174 + to resolve this problem if it is persistent. 1175 + 1176 + 1177 + 1178 + Jenkins & Newman Standards Track [Page 21] 1179 + 1180 + RFC 8620 JMAP July 2019 1181 + 1182 + 1183 + "serverPartialFail": Some, but not all, expected changes described by 1184 + the method occurred. The client MUST resynchronise impacted data to 1185 + determine server state. Use of this error is strongly discouraged. 1186 + 1187 + "unknownMethod": The server does not recognise this method name. 1188 + 1189 + "invalidArguments": One of the arguments is of the wrong type or is 1190 + otherwise invalid, or a required argument is missing. A 1191 + "description" property MAY be present to help debug with an 1192 + explanation of what the problem was. This is a non-localised string, 1193 + and it is not intended to be shown directly to end users. 1194 + 1195 + "invalidResultReference": The method used a result reference for one 1196 + of its arguments (see Section 3.7), but this failed to resolve. 1197 + 1198 + "forbidden": The method and arguments are valid, but executing the 1199 + method would violate an Access Control List (ACL) or other 1200 + permissions policy. 1201 + 1202 + "accountNotFound": The accountId does not correspond to a valid 1203 + account. 1204 + 1205 + "accountNotSupportedByMethod": The accountId given corresponds to a 1206 + valid account, but the account does not support this method or data 1207 + type. 1208 + 1209 + "accountReadOnly": This method modifies state, but the account is 1210 + read-only (as returned on the corresponding Account object in the 1211 + JMAP Session resource). 1212 + 1213 + Further possible errors for a particular method are specified in the 1214 + method descriptions. 1215 + 1216 + Further general errors MAY be defined in future RFCs. Should a 1217 + client receive an error type it does not understand, it MUST treat it 1218 + the same as the "serverFail" type. 1219 + 1220 + 3.7. References to Previous Method Results 1221 + 1222 + To allow clients to make more efficient use of the network and avoid 1223 + round trips, an argument to one method can be taken from the result 1224 + of a previous method call in the same request. 1225 + 1226 + To do this, the client prefixes the argument name with "#" (an 1227 + octothorpe). The value is a ResultReference object as described 1228 + below. When processing a method call, the server MUST first check 1229 + the arguments object for any names beginning with "#". If found, the 1230 + result reference should be resolved and the value used as the "real" 1231 + 1232 + 1233 + 1234 + Jenkins & Newman Standards Track [Page 22] 1235 + 1236 + RFC 8620 JMAP July 2019 1237 + 1238 + 1239 + argument. The method is then processed as normal. If any result 1240 + reference fails to resolve, the whole method MUST be rejected with an 1241 + "invalidResultReference" error. If an arguments object contains the 1242 + same argument name in normal and referenced form (e.g., "foo" and 1243 + "#foo"), the method MUST return an "invalidArguments" error. 1244 + 1245 + A *ResultReference* object has the following properties: 1246 + 1247 + o resultOf: "String" 1248 + 1249 + The method call id (see Section 3.2) of a previous method call in 1250 + the current request. 1251 + 1252 + o name: "String" 1253 + 1254 + The required name of a response to that method call. 1255 + 1256 + o path: "String" 1257 + 1258 + A pointer into the arguments of the response selected via the name 1259 + and resultOf properties. This is a JSON Pointer [RFC6901], except 1260 + it also allows the use of "*" to map through an array (see the 1261 + description below). 1262 + 1263 + To resolve: 1264 + 1265 + 1. Find the first response with a method call id identical to the 1266 + "resultOf" property of the ResultReference in the 1267 + "methodResponses" array from previously processed method calls in 1268 + the same request. If none, evaluation fails. 1269 + 1270 + 2. If the response name is not identical to the "name" property of 1271 + the ResultReference, evaluation fails. 1272 + 1273 + 3. Apply the "path" to the arguments object of the response (the 1274 + second item in the response array) following the JSON Pointer 1275 + algorithm [RFC6901], except with the following addition in 1276 + "Evaluation" (see Section 4): 1277 + 1278 + If the currently referenced value is a JSON array, the reference 1279 + token may be exactly the single character "*", making the new 1280 + referenced value the result of applying the rest of the JSON 1281 + Pointer tokens to every item in the array and returning the 1282 + results in the same order in a new array. If the result of 1283 + applying the rest of the pointer tokens to each item was itself 1284 + an array, the contents of this array are added to the output 1285 + rather than the array itself (i.e., the result is flattened from 1286 + an array of arrays to a single array). If the result of applying 1287 + 1288 + 1289 + 1290 + Jenkins & Newman Standards Track [Page 23] 1291 + 1292 + RFC 8620 JMAP July 2019 1293 + 1294 + 1295 + the rest of the pointer tokens to a value was itself an array, 1296 + its items should be included individually in the output rather 1297 + than including the array itself (i.e., the result is flattened 1298 + from an array of arrays to a single array). 1299 + 1300 + As a simple example, suppose we have the following API request 1301 + "methodCalls": 1302 + 1303 + [[ "Foo/changes", { 1304 + "accountId": "A1", 1305 + "sinceState": "abcdef" 1306 + }, "t0" ], 1307 + [ "Foo/get", { 1308 + "accountId": "A1", 1309 + "#ids": { 1310 + "resultOf": "t0", 1311 + "name": "Foo/changes", 1312 + "path": "/created" 1313 + } 1314 + }, "t1" ]] 1315 + 1316 + After executing the first method call, the "methodResponses" array 1317 + is: 1318 + 1319 + [[ "Foo/changes", { 1320 + "accountId": "A1", 1321 + "oldState": "abcdef", 1322 + "newState": "123456", 1323 + "hasMoreChanges": false, 1324 + "created": [ "f1", "f4" ], 1325 + "updated": [], 1326 + "destroyed": [] 1327 + }, "t0" ]] 1328 + 1329 + To execute the "Foo/get" call, we look through the arguments and find 1330 + there is one with a "#" prefix. To resolve this, we apply the 1331 + algorithm above: 1332 + 1333 + 1. Find the first response with method call id "t0". The "Foo/ 1334 + changes" response fulfils this criterion. 1335 + 1336 + 2. Check that the response name is the same as in the result 1337 + reference. It is, so this is fine. 1338 + 1339 + 3. Apply the "path" as a JSON Pointer to the arguments object. This 1340 + simply selects the "created" property, so the result of 1341 + evaluating is: [ "f1", "f4" ]. 1342 + 1343 + 1344 + 1345 + 1346 + Jenkins & Newman Standards Track [Page 24] 1347 + 1348 + RFC 8620 JMAP July 2019 1349 + 1350 + 1351 + The JMAP server now continues to process the "Foo/get" call as though 1352 + the arguments were: 1353 + 1354 + { 1355 + "accountId": "A1", 1356 + "ids": [ "f1", "f4" ] 1357 + } 1358 + 1359 + Now, a more complicated example using the JMAP Mail data model: fetch 1360 + the "from"/"date"/"subject" for every Email in the first 10 Threads 1361 + in the inbox (sorted newest first): 1362 + 1363 + [[ "Email/query", { 1364 + "accountId": "A1", 1365 + "filter": { "inMailbox": "id_of_inbox" }, 1366 + "sort": [{ "property": "receivedAt", "isAscending": false }], 1367 + "collapseThreads": true, 1368 + "position": 0, 1369 + "limit": 10, 1370 + "calculateTotal": true 1371 + }, "t0" ], 1372 + [ "Email/get", { 1373 + "accountId": "A1", 1374 + "#ids": { 1375 + "resultOf": "t0", 1376 + "name": "Email/query", 1377 + "path": "/ids" 1378 + }, 1379 + "properties": [ "threadId" ] 1380 + }, "t1" ], 1381 + [ "Thread/get", { 1382 + "accountId": "A1", 1383 + "#ids": { 1384 + "resultOf": "t1", 1385 + "name": "Email/get", 1386 + "path": "/list/*/threadId" 1387 + } 1388 + }, "t2" ], 1389 + [ "Email/get", { 1390 + "accountId": "A1", 1391 + "#ids": { 1392 + "resultOf": "t2", 1393 + "name": "Thread/get", 1394 + "path": "/list/*/emailIds" 1395 + }, 1396 + "properties": [ "from", "receivedAt", "subject" ] 1397 + }, "t3" ]] 1398 + 1399 + 1400 + 1401 + 1402 + Jenkins & Newman Standards Track [Page 25] 1403 + 1404 + RFC 8620 JMAP July 2019 1405 + 1406 + 1407 + After executing the first 3 method calls, the "methodResponses" array 1408 + might be: 1409 + 1410 + [[ "Email/query", { 1411 + "accountId": "A1", 1412 + "queryState": "abcdefg", 1413 + "canCalculateChanges": true, 1414 + "position": 0, 1415 + "total": 101, 1416 + "ids": [ "msg1023", "msg223", "msg110", "msg93", "msg91", 1417 + "msg38", "msg36", "msg33", "msg11", "msg1" ] 1418 + }, "t0" ], 1419 + [ "Email/get", { 1420 + "accountId": "A1", 1421 + "state": "123456", 1422 + "list": [{ 1423 + "id": "msg1023", 1424 + "threadId": "trd194" 1425 + }, { 1426 + "id": "msg223", 1427 + "threadId": "trd114" 1428 + }, 1429 + ... 1430 + ], 1431 + "notFound": [] 1432 + }, "t1" ], 1433 + [ "Thread/get", { 1434 + "accountId": "A1", 1435 + "state": "123456", 1436 + "list": [{ 1437 + "id": "trd194", 1438 + "emailIds": [ "msg1020", "msg1021", "msg1023" ] 1439 + }, { 1440 + "id": "trd114", 1441 + "emailIds": [ "msg201", "msg223" ] 1442 + }, 1443 + ... 1444 + ], 1445 + "notFound": [] 1446 + }, "t2" ]] 1447 + 1448 + To execute the final "Email/get" call, we look through the arguments 1449 + and find there is one with a "#" prefix. To resolve this, we apply 1450 + the algorithm: 1451 + 1452 + 1. Find the first response with method call id "t2". The "Thread/ 1453 + get" response fulfils this criterion. 1454 + 1455 + 1456 + 1457 + 1458 + Jenkins & Newman Standards Track [Page 26] 1459 + 1460 + RFC 8620 JMAP July 2019 1461 + 1462 + 1463 + 2. "Thread/get" is the name specified in the result reference, so 1464 + this is fine. 1465 + 1466 + 3. Apply the "path" as a JSON Pointer to the arguments object. 1467 + Token by token: 1468 + 1469 + 1. "list": get the array of thread objects 1470 + 1471 + 2. "*": for each of the items in the array: 1472 + 1473 + a. "emailIds": get the array of Email ids 1474 + 1475 + b. Concatenate these into a single array of all the ids in 1476 + the result. 1477 + 1478 + The JMAP server now continues to process the "Email/get" call as 1479 + though the arguments were: 1480 + 1481 + { 1482 + "accountId": "A1", 1483 + "ids": [ "msg1020", "msg1021", "msg1023", "msg201", "msg223", ... ], 1484 + "properties": [ "from", "receivedAt", "subject" ] 1485 + } 1486 + 1487 + The ResultReference performs a similar role to that of the creation 1488 + id, in that it allows a chained method call to refer to information 1489 + not available when the request is generated. However, they are 1490 + different things and not interchangeable; the only commonality is the 1491 + octothorpe used to indicate them. 1492 + 1493 + 3.8. Localisation of User-Visible Strings 1494 + 1495 + If returning a custom string to be displayed to the user, for 1496 + example, an error message, the server SHOULD use information from the 1497 + Accept-Language header of the request (as defined in Section 5.3.5 of 1498 + [RFC7231]) to choose the best available localisation. The Content- 1499 + Language header of the response (see Section 3.1.3.2 of [RFC7231]) 1500 + SHOULD indicate the language being used for user-visible strings. 1501 + 1502 + For example, suppose a request was made with the following header: 1503 + 1504 + Accept-Language: fr-CH, fr;q=0.9, de;q=0.8, en;q=0.7, *;q=0.5 1505 + 1506 + and a method generated an error to display to the user. The server 1507 + has translations of the error message in English and German. Looking 1508 + at the Accept-Language header, the user's preferred language is 1509 + French. Since we don't have a translation for this, we look at the 1510 + 1511 + 1512 + 1513 + 1514 + Jenkins & Newman Standards Track [Page 27] 1515 + 1516 + RFC 8620 JMAP July 2019 1517 + 1518 + 1519 + next most preferred, which is German. We have a German translation, 1520 + so the server returns this and indicates the language chosen in a 1521 + Content-Language header like so: 1522 + 1523 + Content-Language: de 1524 + 1525 + 3.9. Security 1526 + 1527 + As always, the server must be strict about data received from the 1528 + client. Arguments need to be checked for validity; a malicious user 1529 + could attempt to find an exploit through the API. In case of invalid 1530 + arguments (unknown/insufficient/wrong type for data, etc.), the 1531 + method MUST return an "invalidArguments" error and terminate. 1532 + 1533 + 3.10. Concurrency 1534 + 1535 + Method calls within a single request MUST be executed in order. 1536 + However, method calls from different concurrent API requests may be 1537 + interleaved. This means that the data on the server may change 1538 + between two method calls within a single API request. 1539 + 1540 + 4. The Core/echo Method 1541 + 1542 + The "Core/echo" method returns exactly the same arguments as it is 1543 + given. It is useful for testing if you have a valid authenticated 1544 + connection to a JMAP API endpoint. 1545 + 1546 + 4.1. Example 1547 + 1548 + Request: 1549 + 1550 + [[ "Core/echo", { 1551 + "hello": true, 1552 + "high": 5 1553 + }, "b3ff" ]] 1554 + 1555 + Response: 1556 + 1557 + [[ "Core/echo", { 1558 + "hello": true, 1559 + "high": 5 1560 + }, "b3ff" ]] 1561 + 1562 + 1563 + 1564 + 1565 + 1566 + 1567 + 1568 + 1569 + 1570 + Jenkins & Newman Standards Track [Page 28] 1571 + 1572 + RFC 8620 JMAP July 2019 1573 + 1574 + 1575 + 5. Standard Methods and Naming Convention 1576 + 1577 + JMAP provides a uniform interface for creating, retrieving, updating, 1578 + and deleting objects of a particular type. For a "Foo" data type, 1579 + records of that type would be fetched via a "Foo/get" call and 1580 + modified via a "Foo/set" call. Delta updates may be fetched via a 1581 + "Foo/changes" call. These methods all follow a standard format as 1582 + described below. 1583 + 1584 + Some types may not have all these methods. Specifications defining 1585 + types MUST specify which methods are available for the type. 1586 + 1587 + 5.1. /get 1588 + 1589 + Objects of type Foo are fetched via a call to "Foo/get". 1590 + 1591 + It takes the following arguments: 1592 + 1593 + o accountId: "Id" 1594 + 1595 + The id of the account to use. 1596 + 1597 + o ids: "Id[]|null" 1598 + 1599 + The ids of the Foo objects to return. If null, then *all* records 1600 + of the data type are returned, if this is supported for that data 1601 + type and the number of records does not exceed the 1602 + "maxObjectsInGet" limit. 1603 + 1604 + o properties: "String[]|null" 1605 + 1606 + If supplied, only the properties listed in the array are returned 1607 + for each Foo object. If null, all properties of the object are 1608 + returned. The id property of the object is *always* returned, 1609 + even if not explicitly requested. If an invalid property is 1610 + requested, the call MUST be rejected with an "invalidArguments" 1611 + error. 1612 + 1613 + The response has the following arguments: 1614 + 1615 + o accountId: "Id" 1616 + 1617 + The id of the account used for the call. 1618 + 1619 + 1620 + 1621 + 1622 + 1623 + 1624 + 1625 + 1626 + Jenkins & Newman Standards Track [Page 29] 1627 + 1628 + RFC 8620 JMAP July 2019 1629 + 1630 + 1631 + o state: "String" 1632 + 1633 + A (preferably short) string representing the state on the server 1634 + for *all* the data of this type in the account (not just the 1635 + objects returned in this call). If the data changes, this string 1636 + MUST change. If the Foo data is unchanged, servers SHOULD return 1637 + the same state string on subsequent requests for this data type. 1638 + When a client receives a response with a different state string to 1639 + a previous call, it MUST either throw away all currently cached 1640 + objects for the type or call "Foo/changes" to get the exact 1641 + changes. 1642 + 1643 + o list: "Foo[]" 1644 + 1645 + An array of the Foo objects requested. This is the *empty array* 1646 + if no objects were found or if the "ids" argument passed in was 1647 + also an empty array. The results MAY be in a different order to 1648 + the "ids" in the request arguments. If an identical id is 1649 + included more than once in the request, the server MUST only 1650 + include it once in either the "list" or the "notFound" argument of 1651 + the response. 1652 + 1653 + o notFound: "Id[]" 1654 + 1655 + This array contains the ids passed to the method for records that 1656 + do not exist. The array is empty if all requested ids were found 1657 + or if the "ids" argument passed in was either null or an empty 1658 + array. 1659 + 1660 + The following additional error may be returned instead of the "Foo/ 1661 + get" response: 1662 + 1663 + "requestTooLarge": The number of ids requested by the client exceeds 1664 + the maximum number the server is willing to process in a single 1665 + method call. 1666 + 1667 + 5.2. /changes 1668 + 1669 + When the state of the set of Foo records in an account changes on the 1670 + server (whether due to creation, updates, or deletion), the "state" 1671 + property of the "Foo/get" response will change. The "Foo/changes" 1672 + method allows a client to efficiently update the state of its Foo 1673 + cache to match the new state on the server. It takes the following 1674 + arguments: 1675 + 1676 + o accountId: "Id" 1677 + 1678 + The id of the account to use. 1679 + 1680 + 1681 + 1682 + Jenkins & Newman Standards Track [Page 30] 1683 + 1684 + RFC 8620 JMAP July 2019 1685 + 1686 + 1687 + o sinceState: "String" 1688 + 1689 + The current state of the client. This is the string that was 1690 + returned as the "state" argument in the "Foo/get" response. The 1691 + server will return the changes that have occurred since this 1692 + state. 1693 + 1694 + o maxChanges: "UnsignedInt|null" 1695 + 1696 + The maximum number of ids to return in the response. The server 1697 + MAY choose to return fewer than this value but MUST NOT return 1698 + more. If not given by the client, the server may choose how many 1699 + to return. If supplied by the client, the value MUST be a 1700 + positive integer greater than 0. If a value outside of this range 1701 + is given, the server MUST reject the call with an 1702 + "invalidArguments" error. 1703 + 1704 + The response has the following arguments: 1705 + 1706 + o accountId: "Id" 1707 + 1708 + The id of the account used for the call. 1709 + 1710 + o oldState: "String" 1711 + 1712 + This is the "sinceState" argument echoed back; it's the state from 1713 + which the server is returning changes. 1714 + 1715 + o newState: "String" 1716 + 1717 + This is the state the client will be in after applying the set of 1718 + changes to the old state. 1719 + 1720 + o hasMoreChanges: "Boolean" 1721 + 1722 + If true, the client may call "Foo/changes" again with the 1723 + "newState" returned to get further updates. If false, "newState" 1724 + is the current server state. 1725 + 1726 + o created: "Id[]" 1727 + 1728 + An array of ids for records that have been created since the old 1729 + state. 1730 + 1731 + o updated: "Id[]" 1732 + 1733 + An array of ids for records that have been updated since the old 1734 + state. 1735 + 1736 + 1737 + 1738 + Jenkins & Newman Standards Track [Page 31] 1739 + 1740 + RFC 8620 JMAP July 2019 1741 + 1742 + 1743 + o destroyed: "Id[]" 1744 + 1745 + An array of ids for records that have been destroyed since the old 1746 + state. 1747 + 1748 + If a record has been created AND updated since the old state, the 1749 + server SHOULD just return the id in the "created" list but MAY return 1750 + it in the "updated" list as well. 1751 + 1752 + If a record has been updated AND destroyed since the old state, the 1753 + server SHOULD just return the id in the "destroyed" list but MAY 1754 + return it in the "updated" list as well. 1755 + 1756 + If a record has been created AND destroyed since the old state, the 1757 + server SHOULD remove the id from the response entirely. However, it 1758 + MAY include it in just the "destroyed" list or in both the 1759 + "destroyed" and "created" lists. 1760 + 1761 + If a "maxChanges" is supplied, or set automatically by the server, 1762 + the server MUST ensure the number of ids returned across "created", 1763 + "updated", and "destroyed" does not exceed this limit. If there are 1764 + more changes than this between the client's state and the current 1765 + server state, the server SHOULD generate an update to take the client 1766 + to an intermediate state, from which the client can continue to call 1767 + "Foo/changes" until it is fully up to date. If it is unable to 1768 + calculate an intermediate state, it MUST return a 1769 + "cannotCalculateChanges" error response instead. 1770 + 1771 + When generating intermediate states, the server may choose how to 1772 + divide up the changes. For many types, it will provide a better user 1773 + experience to return the more recent changes first, as this is more 1774 + likely to be what the user is most interested in. The client can 1775 + then continue to page in the older changes while the user is viewing 1776 + the newer data. For example, suppose a server went through the 1777 + following states: 1778 + 1779 + A -> B -> C -> D -> E 1780 + 1781 + And a client asks for changes from state "B". The server might first 1782 + get the ids of records created, updated, or destroyed between states 1783 + D and E, returning them with: 1784 + 1785 + state: "B-D-E" 1786 + hasMoreChanges: true 1787 + 1788 + 1789 + 1790 + 1791 + 1792 + 1793 + 1794 + Jenkins & Newman Standards Track [Page 32] 1795 + 1796 + RFC 8620 JMAP July 2019 1797 + 1798 + 1799 + The client will then ask for the change from state "B-D-E", and the 1800 + server can return the changes between states C and D, returning: 1801 + 1802 + state: "B-C-E" 1803 + hasMoreChanges: true 1804 + 1805 + Finally, the client will request the changes from "B-C-E", and the 1806 + server can return the changes between states B and C, returning: 1807 + 1808 + state: "E" 1809 + hasMoreChanges: false 1810 + 1811 + Should the state on the server be modified in the middle of all this 1812 + (to "F"), the server still does the same, but now when the update to 1813 + state "E" is returned, it would indicate that it still has more 1814 + changes for the client to fetch. 1815 + 1816 + Where multiple changes to a record are split across different 1817 + intermediate states, the server MUST NOT return a record as created 1818 + after a response that deems it as updated or destroyed, and it MUST 1819 + NOT return a record as destroyed before a response that deems it as 1820 + created or updated. The server may have to coalesce multiple changes 1821 + to a record to satisfy this requirement. 1822 + 1823 + The following additional errors may be returned instead of the "Foo/ 1824 + changes" response: 1825 + 1826 + "cannotCalculateChanges": The server cannot calculate the changes 1827 + from the state string given by the client. Usually, this is due to 1828 + the client's state being too old or the server being unable to 1829 + produce an update to an intermediate state when there are too many 1830 + updates. The client MUST invalidate its Foo cache. 1831 + 1832 + Maintaining state to allow calculation of "Foo/changes" can be 1833 + expensive for the server, but always returning 1834 + "cannotCalculateChanges" severely increases network traffic and 1835 + resource usage for the client. To allow efficient sync, servers 1836 + SHOULD be able to calculate changes from any state string that was 1837 + given to a client within the last 30 days (but of course may support 1838 + calculating updates from states older than this). 1839 + 1840 + 1841 + 1842 + 1843 + 1844 + 1845 + 1846 + 1847 + 1848 + 1849 + 1850 + Jenkins & Newman Standards Track [Page 33] 1851 + 1852 + RFC 8620 JMAP July 2019 1853 + 1854 + 1855 + 5.3. /set 1856 + 1857 + Modifying the state of Foo objects on the server is done via the 1858 + "Foo/set" method. This encompasses creating, updating, and 1859 + destroying Foo records. This allows the server to sort out ordering 1860 + and dependencies that may exist if doing multiple operations at once 1861 + (for example, to ensure there is always a minimum number of a certain 1862 + record type). 1863 + 1864 + The "Foo/set" method takes the following arguments: 1865 + 1866 + o accountId: "Id" 1867 + 1868 + The id of the account to use. 1869 + 1870 + o ifInState: "String|null" 1871 + 1872 + This is a state string as returned by the "Foo/get" method 1873 + (representing the state of all objects of this type in the 1874 + account). If supplied, the string must match the current state; 1875 + otherwise, the method will be aborted and a "stateMismatch" error 1876 + returned. If null, any changes will be applied to the current 1877 + state. 1878 + 1879 + o create: "Id[Foo]|null" 1880 + 1881 + A map of a *creation id* (a temporary id set by the client) to Foo 1882 + objects, or null if no objects are to be created. 1883 + 1884 + The Foo object type definition may define default values for 1885 + properties. Any such property may be omitted by the client. 1886 + 1887 + The client MUST omit any properties that may only be set by the 1888 + server (for example, the "id" property on most object types). 1889 + 1890 + o update: "Id[PatchObject]|null" 1891 + 1892 + A map of an id to a Patch object to apply to the current Foo 1893 + object with that id, or null if no objects are to be updated. 1894 + 1895 + A *PatchObject* is of type "String[*]" and represents an unordered 1896 + set of patches. The keys are a path in JSON Pointer format 1897 + [RFC6901], with an implicit leading "/" (i.e., prefix each key 1898 + with "/" before applying the JSON Pointer evaluation algorithm). 1899 + 1900 + All paths MUST also conform to the following restrictions; if 1901 + there is any violation, the update MUST be rejected with an 1902 + "invalidPatch" error: 1903 + 1904 + 1905 + 1906 + Jenkins & Newman Standards Track [Page 34] 1907 + 1908 + RFC 8620 JMAP July 2019 1909 + 1910 + 1911 + * The pointer MUST NOT reference inside an array (i.e., you MUST 1912 + NOT insert/delete from an array; the array MUST be replaced in 1913 + its entirety instead). 1914 + 1915 + * All parts prior to the last (i.e., the value after the final 1916 + slash) MUST already exist on the object being patched. 1917 + 1918 + * There MUST NOT be two patches in the PatchObject where the 1919 + pointer of one is the prefix of the pointer of the other, e.g., 1920 + "alerts/1/offset" and "alerts". 1921 + 1922 + The value associated with each pointer determines how to apply 1923 + that patch: 1924 + 1925 + * If null, set to the default value if specified for this 1926 + property; otherwise, remove the property from the patched 1927 + object. If the key is not present in the parent, this a no-op. 1928 + 1929 + * Anything else: The value to set for this property (this may be 1930 + a replacement or addition to the object being patched). 1931 + 1932 + Any server-set properties MAY be included in the patch if their 1933 + value is identical to the current server value (before applying 1934 + the patches to the object). Otherwise, the update MUST be 1935 + rejected with an "invalidProperties" SetError. 1936 + 1937 + This patch definition is designed such that an entire Foo object 1938 + is also a valid PatchObject. The client may choose to optimise 1939 + network usage by just sending the diff or may send the whole 1940 + object; the server processes it the same either way. 1941 + 1942 + o destroy: "Id[]|null" 1943 + 1944 + A list of ids for Foo objects to permanently delete, or null if no 1945 + objects are to be destroyed. 1946 + 1947 + Each creation, modification, or destruction of an object is 1948 + considered an atomic unit. It is permissible for the server to 1949 + commit changes to some objects but not others; however, it MUST NOT 1950 + only commit part of an update to a single record (e.g., update a 1951 + "name" property but not a "count" property, if both are supplied in 1952 + the update object). 1953 + 1954 + The final state MUST be valid after the "Foo/set" is finished; 1955 + however, the server may have to transition through invalid 1956 + intermediate states (not exposed to the client) while processing the 1957 + individual create/update/destroy requests. For example, suppose 1958 + there is a "name" property that must be unique. A single method call 1959 + 1960 + 1961 + 1962 + Jenkins & Newman Standards Track [Page 35] 1963 + 1964 + RFC 8620 JMAP July 2019 1965 + 1966 + 1967 + could rename an object A => B and simultaneously rename another 1968 + object B => A. If the final state is valid, this is allowed. 1969 + Otherwise, each creation, modification, or destruction of an object 1970 + should be processed sequentially and accepted/rejected based on the 1971 + current server state. 1972 + 1973 + If a create, update, or destroy is rejected, the appropriate error 1974 + MUST be added to the notCreated/notUpdated/notDestroyed property of 1975 + the response, and the server MUST continue to the next create/update/ 1976 + destroy. It does not terminate the method. 1977 + 1978 + If an id given cannot be found, the update or destroy MUST be 1979 + rejected with a "notFound" set error. 1980 + 1981 + The server MAY skip an update (rejecting it with a "willDestroy" 1982 + SetError) if that object is destroyed in the same /set request. 1983 + 1984 + Some records may hold references to other records (foreign keys). 1985 + That reference may be set (via create or update) in the same request 1986 + as the referenced record is created. To do this, the client refers 1987 + to the new record using its creation id prefixed with a "#". The 1988 + order of the method calls in the request by the client MUST be such 1989 + that the record being referenced is created in the same or an earlier 1990 + call. Thus, the server never has to look ahead. Instead, while 1991 + processing a request, the server MUST keep a simple map for the 1992 + duration of the request of creation id to record id for each newly 1993 + created record, so it can substitute in the correct value if 1994 + necessary in later method calls. In the case of records with 1995 + references to the same type, the server MUST order the creates and 1996 + updates within a single method call so that creates happen before 1997 + their creation ids are referenced by another create/update/destroy in 1998 + the same call. 1999 + 2000 + Creation ids are not scoped by type but are a single map for all 2001 + types. A client SHOULD NOT reuse a creation id anywhere in the same 2002 + API request. If a creation id is reused, the server MUST map the 2003 + creation id to the most recently created item with that id. To allow 2004 + easy proxying of API requests, an initial set of creation id to real 2005 + id values may be passed with a request (see "The Request Object", 2006 + Section 3.3) and the final state of the map passed out with the 2007 + response (see "The Response Object", Section 3.4). 2008 + 2009 + The response has the following arguments: 2010 + 2011 + o accountId: "Id" 2012 + 2013 + The id of the account used for the call. 2014 + 2015 + 2016 + 2017 + 2018 + Jenkins & Newman Standards Track [Page 36] 2019 + 2020 + RFC 8620 JMAP July 2019 2021 + 2022 + 2023 + o oldState: "String|null" 2024 + 2025 + The state string that would have been returned by "Foo/get" before 2026 + making the requested changes, or null if the server doesn't know 2027 + what the previous state string was. 2028 + 2029 + o newState: "String" 2030 + 2031 + The state string that will now be returned by "Foo/get". 2032 + 2033 + o created: "Id[Foo]|null" 2034 + 2035 + A map of the creation id to an object containing any properties of 2036 + the created Foo object that were not sent by the client. This 2037 + includes all server-set properties (such as the "id" in most 2038 + object types) and any properties that were omitted by the client 2039 + and thus set to a default by the server. 2040 + 2041 + This argument is null if no Foo objects were successfully created. 2042 + 2043 + o updated: "Id[Foo|null]|null" 2044 + 2045 + The keys in this map are the ids of all Foos that were 2046 + successfully updated. 2047 + 2048 + The value for each id is a Foo object containing any property that 2049 + changed in a way *not* explicitly requested by the PatchObject 2050 + sent to the server, or null if none. This lets the client know of 2051 + any changes to server-set or computed properties. 2052 + 2053 + This argument is null if no Foo objects were successfully updated. 2054 + 2055 + o destroyed: "Id[]|null" 2056 + 2057 + A list of Foo ids for records that were successfully destroyed, or 2058 + null if none. 2059 + 2060 + o notCreated: "Id[SetError]|null" 2061 + 2062 + A map of the creation id to a SetError object for each record that 2063 + failed to be created, or null if all successful. 2064 + 2065 + o notUpdated: "Id[SetError]|null" 2066 + 2067 + A map of the Foo id to a SetError object for each record that 2068 + failed to be updated, or null if all successful. 2069 + 2070 + 2071 + 2072 + 2073 + 2074 + Jenkins & Newman Standards Track [Page 37] 2075 + 2076 + RFC 8620 JMAP July 2019 2077 + 2078 + 2079 + o notDestroyed: "Id[SetError]|null" 2080 + 2081 + A map of the Foo id to a SetError object for each record that 2082 + failed to be destroyed, or null if all successful. 2083 + 2084 + A *SetError* object has the following properties: 2085 + 2086 + o type: "String" 2087 + 2088 + The type of error. 2089 + 2090 + o description: "String|null" 2091 + 2092 + A description of the error to help with debugging that includes an 2093 + explanation of what the problem was. This is a non-localised 2094 + string and is not intended to be shown directly to end users. 2095 + 2096 + The following SetError types are defined and may be returned for set 2097 + operations on any record type where appropriate: 2098 + 2099 + o "forbidden": (create; update; destroy). The create/update/destroy 2100 + would violate an ACL or other permissions policy. 2101 + 2102 + o "overQuota": (create; update). The create would exceed a server- 2103 + defined limit on the number or total size of objects of this type. 2104 + 2105 + o "tooLarge": (create; update). The create/update would result in 2106 + an object that exceeds a server-defined limit for the maximum size 2107 + of a single object of this type. 2108 + 2109 + o "rateLimit": (create). Too many objects of this type have been 2110 + created recently, and a server-defined rate limit has been 2111 + reached. It may work if tried again later. 2112 + 2113 + o "notFound": (update; destroy). The id given to update/destroy 2114 + cannot be found. 2115 + 2116 + o "invalidPatch": (update). The PatchObject given to update the 2117 + record was not a valid patch (see the patch description). 2118 + 2119 + o "willDestroy": (update). The client requested that an object be 2120 + both updated and destroyed in the same /set request, and the 2121 + server has decided to therefore ignore the update. 2122 + 2123 + 2124 + 2125 + 2126 + 2127 + 2128 + 2129 + 2130 + Jenkins & Newman Standards Track [Page 38] 2131 + 2132 + RFC 8620 JMAP July 2019 2133 + 2134 + 2135 + o "invalidProperties": (create; update). The record given is 2136 + invalid in some way. For example: 2137 + 2138 + * It contains properties that are invalid according to the type 2139 + specification of this record type. 2140 + 2141 + * It contains a property that may only be set by the server 2142 + (e.g., "id") and is different to the current value. Note, to 2143 + allow clients to pass whole objects back, it is not an error to 2144 + include a server-set property in an update as long as the value 2145 + is identical to the current value on the server. 2146 + 2147 + * There is a reference to another record (foreign key), and the 2148 + given id does not correspond to a valid record. 2149 + 2150 + The SetError object SHOULD also have a property called 2151 + "properties" of type "String[]" that lists *all* the properties 2152 + that were invalid. 2153 + 2154 + Individual methods MAY specify more specific errors for certain 2155 + conditions that would otherwise result in an invalidProperties 2156 + error. If the condition of one of these is met, it MUST be 2157 + returned instead of the invalidProperties error. 2158 + 2159 + o "singleton": (create; destroy). This is a singleton type, so you 2160 + cannot create another one or destroy the existing one. 2161 + 2162 + Other possible SetError types MAY be given in specific method 2163 + descriptions. Other properties MAY also be present on the SetError 2164 + object, as described in the relevant methods. 2165 + 2166 + The following additional errors may be returned instead of the "Foo/ 2167 + set" response: 2168 + 2169 + "requestTooLarge": The total number of objects to create, update, or 2170 + destroy exceeds the maximum number the server is willing to process 2171 + in a single method call. 2172 + 2173 + "stateMismatch": An "ifInState" argument was supplied, and it does 2174 + not match the current state. 2175 + 2176 + 2177 + 2178 + 2179 + 2180 + 2181 + 2182 + 2183 + 2184 + 2185 + 2186 + Jenkins & Newman Standards Track [Page 39] 2187 + 2188 + RFC 8620 JMAP July 2019 2189 + 2190 + 2191 + 5.4. /copy 2192 + 2193 + The only way to move Foo records *between* two different accounts is 2194 + to copy them using the "Foo/copy" method; once the copy has 2195 + succeeded, delete the original. The "onSuccessDestroyOriginal" 2196 + argument allows you to try to do this in one method call; however, 2197 + note that the two different actions are not atomic, so it is possible 2198 + for the copy to succeed but the original not to be destroyed for some 2199 + reason. 2200 + 2201 + The copy is conceptually in three phases: 2202 + 2203 + 1. Reading the current values from the "from" account. 2204 + 2205 + 2. Writing the new copies to the other account. 2206 + 2207 + 3. Destroying the originals in the "from" account, if requested. 2208 + 2209 + Data may change in between phases due to concurrent requests. 2210 + 2211 + The "Foo/copy" method takes the following arguments: 2212 + 2213 + o fromAccountId: "Id" 2214 + 2215 + The id of the account to copy records from. 2216 + 2217 + o ifFromInState: "String|null" 2218 + 2219 + This is a state string as returned by the "Foo/get" method. If 2220 + supplied, the string must match the current state of the account 2221 + referenced by the fromAccountId when reading the data to be 2222 + copied; otherwise, the method will be aborted and a 2223 + "stateMismatch" error returned. If null, the data will be read 2224 + from the current state. 2225 + 2226 + o accountId: "Id" 2227 + 2228 + The id of the account to copy records to. This MUST be different 2229 + to the "fromAccountId". 2230 + 2231 + o ifInState: "String|null" 2232 + 2233 + This is a state string as returned by the "Foo/get" method. If 2234 + supplied, the string must match the current state of the account 2235 + referenced by the accountId; otherwise, the method will be aborted 2236 + and a "stateMismatch" error returned. If null, any changes will 2237 + be applied to the current state. 2238 + 2239 + 2240 + 2241 + 2242 + Jenkins & Newman Standards Track [Page 40] 2243 + 2244 + RFC 8620 JMAP July 2019 2245 + 2246 + 2247 + o create: "Id[Foo]" 2248 + 2249 + A map of the *creation id* to a Foo object. The Foo object MUST 2250 + contain an "id" property, which is the id (in the fromAccount) of 2251 + the record to be copied. When creating the copy, any other 2252 + properties included are used instead of the current value for that 2253 + property on the original. 2254 + 2255 + o onSuccessDestroyOriginal: "Boolean" (default: false) 2256 + 2257 + If true, an attempt will be made to destroy the original records 2258 + that were successfully copied: after emitting the "Foo/copy" 2259 + response, but before processing the next method, the server MUST 2260 + make a single call to "Foo/set" to destroy the original of each 2261 + successfully copied record; the output of this is added to the 2262 + responses as normal, to be returned to the client. 2263 + 2264 + o destroyFromIfInState: "String|null" 2265 + 2266 + This argument is passed on as the "ifInState" argument to the 2267 + implicit "Foo/set" call, if made at the end of this request to 2268 + destroy the originals that were successfully copied. 2269 + 2270 + Each record copy is considered an atomic unit that may succeed or 2271 + fail individually. 2272 + 2273 + The response has the following arguments: 2274 + 2275 + o fromAccountId: "Id" 2276 + 2277 + The id of the account records were copied from. 2278 + 2279 + o accountId: "Id" 2280 + 2281 + The id of the account records were copied to. 2282 + 2283 + o oldState: "String|null" 2284 + 2285 + The state string that would have been returned by "Foo/get" on the 2286 + account records that were copied to before making the requested 2287 + changes, or null if the server doesn't know what the previous 2288 + state string was. 2289 + 2290 + o newState: "String" 2291 + 2292 + The state string that will now be returned by "Foo/get" on the 2293 + account records were copied to. 2294 + 2295 + 2296 + 2297 + 2298 + Jenkins & Newman Standards Track [Page 41] 2299 + 2300 + RFC 8620 JMAP July 2019 2301 + 2302 + 2303 + o created: "Id[Foo]|null" 2304 + 2305 + A map of the creation id to an object containing any properties of 2306 + the copied Foo object that are set by the server (such as the "id" 2307 + in most object types; note, the id is likely to be different to 2308 + the id of the object in the account it was copied from). 2309 + 2310 + This argument is null if no Foo objects were successfully copied. 2311 + 2312 + o notCreated: "Id[SetError]|null" 2313 + 2314 + A map of the creation id to a SetError object for each record that 2315 + failed to be copied, or null if none. 2316 + 2317 + The SetError may be any of the standard set errors returned for a 2318 + create or update. In addition, the following SetError is defined: 2319 + 2320 + "alreadyExists": The server forbids duplicates, and the record 2321 + already exists in the target account. An "existingId" property of 2322 + type "Id" MUST be included on the SetError object with the id of the 2323 + existing record. 2324 + 2325 + The following additional errors may be returned instead of the "Foo/ 2326 + copy" response: 2327 + 2328 + "fromAccountNotFound": The "fromAccountId" does not correspond to a 2329 + valid account. 2330 + 2331 + "fromAccountNotSupportedByMethod": The "fromAccountId" given 2332 + corresponds to a valid account, but the account does not support this 2333 + data type. 2334 + 2335 + "stateMismatch": An "ifInState" argument was supplied and it does not 2336 + match the current state, or an "ifFromInState" argument was supplied 2337 + and it does not match the current state in the from account. 2338 + 2339 + 5.5. /query 2340 + 2341 + For data sets where the total amount of data is expected to be very 2342 + small, clients can just fetch the complete set of data and then do 2343 + any sorting/filtering locally. However, for large data sets (e.g., 2344 + multi-gigabyte mailboxes), the client needs to be able to 2345 + search/sort/window the data type on the server. 2346 + 2347 + A query on the set of Foos in an account is made by calling "Foo/ 2348 + query". This takes a number of arguments to determine which records 2349 + to include, how they should be sorted, and which part of the result 2350 + 2351 + 2352 + 2353 + 2354 + Jenkins & Newman Standards Track [Page 42] 2355 + 2356 + RFC 8620 JMAP July 2019 2357 + 2358 + 2359 + should be returned (the full list may be *very* long). The result is 2360 + returned as a list of Foo ids. 2361 + 2362 + A call to "Foo/query" takes the following arguments: 2363 + 2364 + o accountId: "Id" 2365 + 2366 + The id of the account to use. 2367 + 2368 + o filter: "FilterOperator|FilterCondition|null" 2369 + 2370 + Determines the set of Foos returned in the results. If null, all 2371 + objects in the account of this type are included in the results. 2372 + A *FilterOperator* object has the following properties: 2373 + 2374 + * operator: "String" 2375 + 2376 + This MUST be one of the following strings: 2377 + 2378 + + "AND": All of the conditions must match for the filter to 2379 + match. 2380 + 2381 + + "OR": At least one of the conditions must match for the 2382 + filter to match. 2383 + 2384 + + "NOT": None of the conditions must match for the filter to 2385 + match. 2386 + 2387 + * conditions: "(FilterOperator|FilterCondition)[]" 2388 + 2389 + The conditions to evaluate against each record. 2390 + 2391 + A *FilterCondition* is an "object" whose allowed properties and 2392 + semantics depend on the data type and is defined in the /query 2393 + method specification for that type. It MUST NOT have an 2394 + "operator" property. 2395 + 2396 + o sort: "Comparator[]|null" 2397 + 2398 + Lists the names of properties to compare between two Foo records, 2399 + and how to compare them, to determine which comes first in the 2400 + sort. If two Foo records have an identical value for the first 2401 + comparator, the next comparator will be considered, and so on. If 2402 + all comparators are the same (this includes the case where an 2403 + empty array or null is given as the "sort" argument), the sort 2404 + order is server dependent, but it MUST be stable between calls to 2405 + "Foo/query". A *Comparator* has the following properties: 2406 + 2407 + 2408 + 2409 + 2410 + Jenkins & Newman Standards Track [Page 43] 2411 + 2412 + RFC 8620 JMAP July 2019 2413 + 2414 + 2415 + * property: "String" 2416 + 2417 + The name of the property on the Foo objects to compare. 2418 + 2419 + * isAscending: "Boolean" (optional; default: true) 2420 + 2421 + If true, sort in ascending order. If false, reverse the 2422 + comparator's results to sort in descending order. 2423 + 2424 + * collation: "String" (optional; default is server-dependent) 2425 + 2426 + The identifier, as registered in the collation registry defined 2427 + in [RFC4790], for the algorithm to use when comparing the order 2428 + of strings. The algorithms the server supports are advertised 2429 + in the capabilities object returned with the Session object 2430 + (see Section 2). 2431 + 2432 + If omitted, the default algorithm is server dependent, but: 2433 + 2434 + 1. It MUST be unicode-aware. 2435 + 2436 + 2. It MAY be selected based on an Accept-Language header in 2437 + the request (as defined in [RFC7231], Section 5.3.5) or 2438 + out-of-band information about the user's language/locale. 2439 + 2440 + 3. It SHOULD be case insensitive where such a concept makes 2441 + sense for a language/locale. Where the user's language is 2442 + unknown, it is RECOMMENDED to follow the advice in 2443 + Section 5.2.3 of [RFC8264]. 2444 + 2445 + The "i;unicode-casemap" collation [RFC5051] and the Unicode 2446 + Collation Algorithm (<http://www.unicode.org/reports/tr10/>) 2447 + are two examples that fulfil these criterion and provide 2448 + reasonable behaviour for a large number of languages. 2449 + 2450 + When the property being compared is not a string, the 2451 + "collation" property is ignored, and the following comparison 2452 + rules apply based on the type. In ascending order: 2453 + 2454 + + "Boolean": false comes before true. 2455 + 2456 + + "Number": A lower number comes before a higher number. 2457 + 2458 + + "Date"/"UTCDate": The earlier date comes first. 2459 + 2460 + The Comparator object may also have additional properties as 2461 + required for specific sort operations defined in a type's /query 2462 + method. 2463 + 2464 + 2465 + 2466 + Jenkins & Newman Standards Track [Page 44] 2467 + 2468 + RFC 8620 JMAP July 2019 2469 + 2470 + 2471 + o position: "Int" (default: 0) 2472 + 2473 + The zero-based index of the first id in the full list of results 2474 + to return. 2475 + 2476 + If a negative value is given, it is an offset from the end of the 2477 + list. Specifically, the negative value MUST be added to the total 2478 + number of results given the filter, and if still negative, it's 2479 + clamped to "0". This is now the zero-based index of the first id 2480 + to return. 2481 + 2482 + If the index is greater than or equal to the total number of 2483 + objects in the results list, then the "ids" array in the response 2484 + will be empty, but this is not an error. 2485 + 2486 + o anchor: "Id|null" 2487 + 2488 + A Foo id. If supplied, the "position" argument is ignored. The 2489 + index of this id in the results will be used in combination with 2490 + the "anchorOffset" argument to determine the index of the first 2491 + result to return (see below for more details). 2492 + 2493 + o anchorOffset: "Int" (default: 0) 2494 + 2495 + The index of the first result to return relative to the index of 2496 + the anchor, if an anchor is given. This MAY be negative. For 2497 + example, "-1" means the Foo immediately preceding the anchor is 2498 + the first result in the list returned (see below for more 2499 + details). 2500 + 2501 + o limit: "UnsignedInt|null" 2502 + 2503 + The maximum number of results to return. If null, no limit 2504 + presumed. The server MAY choose to enforce a maximum "limit" 2505 + argument. In this case, if a greater value is given (or if it is 2506 + null), the limit is clamped to the maximum; the new limit is 2507 + returned with the response so the client is aware. If a negative 2508 + value is given, the call MUST be rejected with an 2509 + "invalidArguments" error. 2510 + 2511 + o calculateTotal: "Boolean" (default: false) 2512 + 2513 + Does the client wish to know the total number of results in the 2514 + query? This may be slow and expensive for servers to calculate, 2515 + particularly with complex filters, so clients should take care to 2516 + only request the total when needed. 2517 + 2518 + 2519 + 2520 + 2521 + 2522 + Jenkins & Newman Standards Track [Page 45] 2523 + 2524 + RFC 8620 JMAP July 2019 2525 + 2526 + 2527 + If an "anchor" argument is given, the anchor is looked for in the 2528 + results after filtering and sorting. If found, the "anchorOffset" is 2529 + then added to its index. If the resulting index is now negative, it 2530 + is clamped to 0. This index is now used exactly as though it were 2531 + supplied as the "position" argument. If the anchor is not found, the 2532 + call is rejected with an "anchorNotFound" error. 2533 + 2534 + If an "anchor" is specified, any position argument supplied by the 2535 + client MUST be ignored. If no "anchor" is supplied, any 2536 + "anchorOffset" argument MUST be ignored. 2537 + 2538 + A client can use "anchor" instead of "position" to find the index of 2539 + an id within a large set of results. 2540 + 2541 + The response has the following arguments: 2542 + 2543 + o accountId: "Id" 2544 + 2545 + The id of the account used for the call. 2546 + 2547 + o queryState: "String" 2548 + 2549 + A string encoding the current state of the query on the server. 2550 + This string MUST change if the results of the query (i.e., the 2551 + matching ids and their sort order) have changed. The queryState 2552 + string MAY change if something has changed on the server, which 2553 + means the results may have changed but the server doesn't know for 2554 + sure. 2555 + 2556 + The queryState string only represents the ordered list of ids that 2557 + match the particular query (including its sort/filter). There is 2558 + no requirement for it to change if a property on an object 2559 + matching the query changes but the query results are unaffected 2560 + (indeed, it is more efficient if the queryState string does not 2561 + change in this case). The queryState string only has meaning when 2562 + compared to future responses to a query with the same type/sort/ 2563 + filter or when used with /queryChanges to fetch changes. 2564 + 2565 + Should a client receive back a response with a different 2566 + queryState string to a previous call, it MUST either throw away 2567 + the currently cached query and fetch it again (note, this does not 2568 + require fetching the records again, just the list of ids) or call 2569 + "Foo/queryChanges" to get the difference. 2570 + 2571 + 2572 + 2573 + 2574 + 2575 + 2576 + 2577 + 2578 + Jenkins & Newman Standards Track [Page 46] 2579 + 2580 + RFC 8620 JMAP July 2019 2581 + 2582 + 2583 + o canCalculateChanges: "Boolean" 2584 + 2585 + This is true if the server supports calling "Foo/queryChanges" 2586 + with these "filter"/"sort" parameters. Note, this does not 2587 + guarantee that the "Foo/queryChanges" call will succeed, as it may 2588 + only be possible for a limited time afterwards due to server 2589 + internal implementation details. 2590 + 2591 + o position: "UnsignedInt" 2592 + 2593 + The zero-based index of the first result in the "ids" array within 2594 + the complete list of query results. 2595 + 2596 + o ids: "Id[]" 2597 + 2598 + The list of ids for each Foo in the query results, starting at the 2599 + index given by the "position" argument of this response and 2600 + continuing until it hits the end of the results or reaches the 2601 + "limit" number of ids. If "position" is >= "total", this MUST be 2602 + the empty list. 2603 + 2604 + o total: "UnsignedInt" (only if requested) 2605 + 2606 + The total number of Foos in the results (given the "filter"). 2607 + This argument MUST be omitted if the "calculateTotal" request 2608 + argument is not true. 2609 + 2610 + o limit: "UnsignedInt" (if set by the server) 2611 + 2612 + The limit enforced by the server on the maximum number of results 2613 + to return. This is only returned if the server set a limit or 2614 + used a different limit than that given in the request. 2615 + 2616 + The following additional errors may be returned instead of the "Foo/ 2617 + query" response: 2618 + 2619 + "anchorNotFound": An anchor argument was supplied, but it cannot be 2620 + found in the results of the query. 2621 + 2622 + "unsupportedSort": The "sort" is syntactically valid, but it includes 2623 + a property the server does not support sorting on or a collation 2624 + method it does not recognise. 2625 + 2626 + "unsupportedFilter": The "filter" is syntactically valid, but the 2627 + server cannot process it. If the filter was the result of a user's 2628 + search input, the client SHOULD suggest that the user simplify their 2629 + search. 2630 + 2631 + 2632 + 2633 + 2634 + Jenkins & Newman Standards Track [Page 47] 2635 + 2636 + RFC 8620 JMAP July 2019 2637 + 2638 + 2639 + 5.6. /queryChanges 2640 + 2641 + The "Foo/queryChanges" method allows a client to efficiently update 2642 + the state of a cached query to match the new state on the server. It 2643 + takes the following arguments: 2644 + 2645 + o accountId: "Id" 2646 + 2647 + The id of the account to use. 2648 + 2649 + o filter: "FilterOperator|FilterCondition|null" 2650 + 2651 + The filter argument that was used with "Foo/query". 2652 + 2653 + o sort: "Comparator[]|null" 2654 + 2655 + The sort argument that was used with "Foo/query". 2656 + 2657 + o sinceQueryState: "String" 2658 + 2659 + The current state of the query in the client. This is the string 2660 + that was returned as the "queryState" argument in the "Foo/query" 2661 + response with the same sort/filter. The server will return the 2662 + changes made to the query since this state. 2663 + 2664 + o maxChanges: "UnsignedInt|null" 2665 + 2666 + The maximum number of changes to return in the response. See 2667 + error descriptions below for more details. 2668 + 2669 + o upToId: "Id|null" 2670 + 2671 + The last (highest-index) id the client currently has cached from 2672 + the query results. When there are a large number of results, in a 2673 + common case, the client may have only downloaded and cached a 2674 + small subset from the beginning of the results. If the sort and 2675 + filter are both only on immutable properties, this allows the 2676 + server to omit changes after this point in the results, which can 2677 + significantly increase efficiency. If they are not immutable, 2678 + this argument is ignored. 2679 + 2680 + o calculateTotal: "Boolean" (default: false) 2681 + 2682 + Does the client wish to know the total number of results now in 2683 + the query? This may be slow and expensive for servers to 2684 + calculate, particularly with complex filters, so clients should 2685 + take care to only request the total when needed. 2686 + 2687 + 2688 + 2689 + 2690 + Jenkins & Newman Standards Track [Page 48] 2691 + 2692 + RFC 8620 JMAP July 2019 2693 + 2694 + 2695 + The response has the following arguments: 2696 + 2697 + o accountId: "Id" 2698 + 2699 + The id of the account used for the call. 2700 + 2701 + o oldQueryState: "String" 2702 + 2703 + This is the "sinceQueryState" argument echoed back; that is, the 2704 + state from which the server is returning changes. 2705 + 2706 + o newQueryState: "String" 2707 + 2708 + This is the state the query will be in after applying the set of 2709 + changes to the old state. 2710 + 2711 + o total: "UnsignedInt" (only if requested) 2712 + 2713 + The total number of Foos in the results (given the "filter"). 2714 + This argument MUST be omitted if the "calculateTotal" request 2715 + argument is not true. 2716 + 2717 + o removed: "Id[]" 2718 + 2719 + The "id" for every Foo that was in the query results in the old 2720 + state and that is not in the results in the new state. 2721 + 2722 + If the server cannot calculate this exactly, the server MAY return 2723 + the ids of extra Foos in addition that may have been in the old 2724 + results but are not in the new results. 2725 + 2726 + If the sort and filter are both only on immutable properties and 2727 + an "upToId" is supplied and exists in the results, any ids that 2728 + were removed but have a higher index than "upToId" SHOULD be 2729 + omitted. 2730 + 2731 + If the "filter" or "sort" includes a mutable property, the server 2732 + MUST include all Foos in the current results for which this 2733 + property may have changed. The position of these may have moved 2734 + in the results, so they must be reinserted by the client to ensure 2735 + its query cache is correct. 2736 + 2737 + 2738 + 2739 + 2740 + 2741 + 2742 + 2743 + 2744 + 2745 + 2746 + Jenkins & Newman Standards Track [Page 49] 2747 + 2748 + RFC 8620 JMAP July 2019 2749 + 2750 + 2751 + o added: "AddedItem[]" 2752 + 2753 + The id and index in the query results (in the new state) for every 2754 + Foo that has been added to the results since the old state AND 2755 + every Foo in the current results that was included in the 2756 + "removed" array (due to a filter or sort based upon a mutable 2757 + property). 2758 + 2759 + If the sort and filter are both only on immutable properties and 2760 + an "upToId" is supplied and exists in the results, any ids that 2761 + were added but have a higher index than "upToId" SHOULD be 2762 + omitted. 2763 + 2764 + The array MUST be sorted in order of index, with the lowest index 2765 + first. 2766 + 2767 + An *AddedItem* object has the following properties: 2768 + 2769 + * id: "Id" 2770 + 2771 + * index: "UnsignedInt" 2772 + 2773 + The result of this is that if the client has a cached sparse array of 2774 + Foo ids corresponding to the results in the old state, then: 2775 + 2776 + fooIds = [ "id1", "id2", null, null, "id3", "id4", null, null, null ] 2777 + 2778 + If it *splices out* all ids in the removed array that it has in its 2779 + cached results, then: 2780 + 2781 + removed = [ "id2", "id31", ... ]; 2782 + fooIds => [ "id1", null, null, "id3", "id4", null, null, null ] 2783 + 2784 + and *splices in* (one by one in order, starting with the lowest 2785 + index) all of the ids in the added array: 2786 + 2787 + added = [{ id: "id5", index: 0, ... }]; 2788 + fooIds => [ "id5", "id1", null, null, "id3", "id4", null, null, null ] 2789 + 2790 + and *truncates* or *extends* to the new total length, then the 2791 + results will now be in the new state. 2792 + 2793 + Note: splicing in adds the item at the given index, incrementing the 2794 + index of all items previously at that or a higher index. Splicing 2795 + out is the inverse, removing the item and decrementing the index of 2796 + every item after it in the array. 2797 + 2798 + 2799 + 2800 + 2801 + 2802 + Jenkins & Newman Standards Track [Page 50] 2803 + 2804 + RFC 8620 JMAP July 2019 2805 + 2806 + 2807 + The following additional errors may be returned instead of the "Foo/ 2808 + queryChanges" response: 2809 + 2810 + "tooManyChanges": There are more changes than the client's 2811 + "maxChanges" argument. Each item in the removed or added array is 2812 + considered to be one change. The client may retry with higher max 2813 + changes or invalidate its cache of the query results. 2814 + 2815 + "cannotCalculateChanges": The server cannot calculate the changes 2816 + from the queryState string given by the client, usually due to the 2817 + client's state being too old. The client MUST invalidate its cache 2818 + of the query results. 2819 + 2820 + 5.7. Examples 2821 + 2822 + Suppose we have a type *Todo* with the following properties: 2823 + 2824 + o id: "Id" (immutable; server-set) 2825 + 2826 + The id of the object. 2827 + 2828 + o title: "String" 2829 + 2830 + A brief summary of what is to be done. 2831 + 2832 + o keywords: "String[Boolean]" (default: {}) 2833 + 2834 + A set of keywords that apply to the Todo. The set is represented 2835 + as an object, with the keys being the "keywords". The value for 2836 + each key in the object MUST be true. (This format allows you to 2837 + update an individual key using patch syntax rather than having to 2838 + update the whole set of keywords as one, which a "String[]" 2839 + representation would require.) 2840 + 2841 + o neuralNetworkTimeEstimation: "Number" (server-set) 2842 + 2843 + The title and keywords are fed into the server's state-of-the-art 2844 + neural network to get an estimation of how long this Todo will 2845 + take, in seconds. 2846 + 2847 + o subTodoIds: "Id[]|null" 2848 + 2849 + The ids of a list of other Todos to complete as part of this Todo. 2850 + 2851 + Suppose also that all the standard methods are defined for this type 2852 + and the FilterCondition object supports a "hasKeyword" property to 2853 + match Todos with the given keyword. 2854 + 2855 + 2856 + 2857 + 2858 + Jenkins & Newman Standards Track [Page 51] 2859 + 2860 + RFC 8620 JMAP July 2019 2861 + 2862 + 2863 + A client might want to display the list of Todos with either a 2864 + "music" keyword or a "video" keyword, so it makes the following 2865 + method call: 2866 + 2867 + [[ "Todo/query", { 2868 + "accountId": "x", 2869 + "filter": { 2870 + "operator": "OR", 2871 + "conditions": [ 2872 + { "hasKeyword": "music" }, 2873 + { "hasKeyword": "video" } 2874 + ] 2875 + }, 2876 + "sort": [{ "property": "title" }], 2877 + "position": 0, 2878 + "limit": 10 2879 + }, "0" ], 2880 + [ "Todo/get", { 2881 + "accountId": "x", 2882 + "#ids": { 2883 + "resultOf": "0", 2884 + "name": "Todo/query", 2885 + "path": "/ids" 2886 + } 2887 + }, "1" ]] 2888 + 2889 + 2890 + 2891 + 2892 + 2893 + 2894 + 2895 + 2896 + 2897 + 2898 + 2899 + 2900 + 2901 + 2902 + 2903 + 2904 + 2905 + 2906 + 2907 + 2908 + 2909 + 2910 + 2911 + 2912 + 2913 + 2914 + Jenkins & Newman Standards Track [Page 52] 2915 + 2916 + RFC 8620 JMAP July 2019 2917 + 2918 + 2919 + This would query the server for the set of Todos with a keyword of 2920 + either "music" or "video", sorted by title, and limited to the first 2921 + 10 results. It fetches the full object for each of these Todos using 2922 + back-references to reference the result of the query. The response 2923 + might look something like: 2924 + 2925 + [[ "Todo/query", { 2926 + "accountId": "x", 2927 + "queryState": "y13213", 2928 + "canCalculateChanges": true, 2929 + "position": 0, 2930 + "ids": [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ] 2931 + }, "0" ], 2932 + [ "Todo/get", { 2933 + "accountId": "x", 2934 + "state": "10324", 2935 + "list": [{ 2936 + "id": "a", 2937 + "title": "Practise Piano", 2938 + "keywords": { 2939 + "music": true, 2940 + "beethoven": true, 2941 + "mozart": true, 2942 + "liszt": true, 2943 + "rachmaninov": true 2944 + }, 2945 + "neuralNetworkTimeEstimation": 3600 2946 + }, { 2947 + "id": "b", 2948 + "title": "Watch Daft Punk music video", 2949 + "keywords": { 2950 + "music": true, 2951 + "video": true, 2952 + "trance": true 2953 + }, 2954 + "neuralNetworkTimeEstimation": 18000 2955 + }, 2956 + ... 2957 + ] 2958 + }, "1" ]] 2959 + 2960 + 2961 + 2962 + 2963 + 2964 + 2965 + 2966 + 2967 + 2968 + 2969 + 2970 + Jenkins & Newman Standards Track [Page 53] 2971 + 2972 + RFC 8620 JMAP July 2019 2973 + 2974 + 2975 + Now, suppose the user adds a keyword "chopin" and removes the keyword 2976 + "mozart" from the "Practise Piano" task. The client may send the 2977 + whole object to the server, as this is a valid PatchObject: 2978 + 2979 + [[ "Todo/set", { 2980 + "accountId": "x", 2981 + "ifInState": "10324", 2982 + "update": { 2983 + "a": { 2984 + "id": "a", 2985 + "title": "Practise Piano", 2986 + "keywords": { 2987 + "music": true, 2988 + "beethoven": true, 2989 + "chopin": true, 2990 + "liszt": true, 2991 + "rachmaninov": true 2992 + }, 2993 + "neuralNetworkTimeEstimation": 360 2994 + } 2995 + } 2996 + }, "0" ]] 2997 + 2998 + or it may send a minimal patch: 2999 + 3000 + [[ "Todo/set", { 3001 + "accountId": "x", 3002 + "ifInState": "10324", 3003 + "update": { 3004 + "a": { 3005 + "keywords/chopin": true, 3006 + "keywords/mozart": null 3007 + } 3008 + } 3009 + }, "0" ]] 3010 + 3011 + 3012 + 3013 + 3014 + 3015 + 3016 + 3017 + 3018 + 3019 + 3020 + 3021 + 3022 + 3023 + 3024 + 3025 + 3026 + Jenkins & Newman Standards Track [Page 54] 3027 + 3028 + RFC 8620 JMAP July 2019 3029 + 3030 + 3031 + The effect is exactly the same on the server in either case, and 3032 + presuming the server is still in state "10324", it will probably 3033 + return success: 3034 + 3035 + [[ "Todo/set", { 3036 + "accountId": "x", 3037 + "oldState": "10324", 3038 + "newState": "10329", 3039 + "updated": { 3040 + "a": { 3041 + "neuralNetworkTimeEstimation": 5400 3042 + } 3043 + } 3044 + }, "0" ]] 3045 + 3046 + The server changed the "neuralNetworkTimeEstimation" property on the 3047 + object as part of this change; as this changed in a way *not* 3048 + explicitly requested by the PatchObject sent to the server, it is 3049 + returned with the "updated" confirmation. 3050 + 3051 + Let us now add a sub-Todo to our new "Practise Piano" Todo. In this 3052 + example, we can see the use of a reference to a creation id to allow 3053 + us to set a foreign key reference to a record created in the same 3054 + request: 3055 + 3056 + [[ "Todo/set", { 3057 + "accountId": "x", 3058 + "create": { 3059 + "k15": { 3060 + "title": "Warm up with scales" 3061 + } 3062 + }, 3063 + "update": { 3064 + "a": { 3065 + "subTodoIds": [ "#k15" ] 3066 + } 3067 + } 3068 + }, "0" ]] 3069 + 3070 + 3071 + 3072 + 3073 + 3074 + 3075 + 3076 + 3077 + 3078 + 3079 + 3080 + 3081 + 3082 + Jenkins & Newman Standards Track [Page 55] 3083 + 3084 + RFC 8620 JMAP July 2019 3085 + 3086 + 3087 + Now, suppose another user deleted the "Listen to Daft Punk" Todo. 3088 + The first user will receive a push notification (see Section 7) with 3089 + the changed state string for the "Todo" type. Since the new string 3090 + does not match its current state, it knows it needs to check for 3091 + updates. It may make a request like: 3092 + 3093 + [[ "Todo/changes", { 3094 + "accountId": "x", 3095 + "sinceState": "10324", 3096 + "maxChanges": 50 3097 + }, "0" ], 3098 + [ "Todo/queryChanges", { 3099 + "accountId": "x", 3100 + "filter": { 3101 + "operator": "OR", 3102 + "conditions": [ 3103 + { "hasKeyword": "music" }, 3104 + { "hasKeyword": "video" } 3105 + ] 3106 + }, 3107 + "sort": [{ "property": "title" }], 3108 + "sinceQueryState": "y13213", 3109 + "maxChanges": 50 3110 + }, "1" ]] 3111 + 3112 + and receive in response: 3113 + 3114 + [[ "Todo/changes", { 3115 + "accountId": "x", 3116 + "oldState": "10324", 3117 + "newState": "871903", 3118 + "hasMoreChanges": false, 3119 + "created": [], 3120 + "updated": [], 3121 + "destroyed": ["b"] 3122 + }, "0" ], 3123 + [ "Todo/queryChanges", { 3124 + "accountId": "x", 3125 + "oldQueryState": "y13213", 3126 + "newQueryState": "y13218", 3127 + "removed": ["b"], 3128 + "added": null 3129 + }, "1" ]] 3130 + 3131 + 3132 + 3133 + 3134 + 3135 + 3136 + 3137 + 3138 + Jenkins & Newman Standards Track [Page 56] 3139 + 3140 + RFC 8620 JMAP July 2019 3141 + 3142 + 3143 + Suppose the user has access to another account "y", for example, a 3144 + team account shared between multiple users. To move an existing Todo 3145 + from account "x", the client would call: 3146 + 3147 + [[ "Todo/copy", { 3148 + "fromAccountId": "x", 3149 + "accountId": "y", 3150 + "create": { 3151 + "k5122": { 3152 + "id": "a" 3153 + } 3154 + }, 3155 + "onSuccessDestroyOriginal": true 3156 + }, "0" ]] 3157 + 3158 + The server successfully copies the Todo to a new account (where it 3159 + receives a new id) and deletes the original. Due to the implicit 3160 + call to "Todo/set", there are two responses to the single method 3161 + call, both with the same method call id: 3162 + 3163 + [[ "Todo/copy", { 3164 + "fromAccountId": "x", 3165 + "accountId": "y", 3166 + "created": { 3167 + "k5122": { 3168 + "id": "DAf97" 3169 + } 3170 + }, 3171 + "oldState": "c1d64ecb038c", 3172 + "newState": "33844835152b" 3173 + }, "0" ], 3174 + [ "Todo/set", { 3175 + "accountId": "x", 3176 + "oldState": "871903", 3177 + "newState": "871909", 3178 + "destroyed": [ "a" ], 3179 + ... 3180 + }, "0" ]] 3181 + 3182 + 3183 + 3184 + 3185 + 3186 + 3187 + 3188 + 3189 + 3190 + 3191 + 3192 + 3193 + 3194 + Jenkins & Newman Standards Track [Page 57] 3195 + 3196 + RFC 8620 JMAP July 2019 3197 + 3198 + 3199 + 5.8. Proxy Considerations 3200 + 3201 + JMAP has been designed to allow an API endpoint to easily proxy 3202 + through to one or more JMAP servers. This may be useful for load 3203 + balancing, augmenting capabilities, or presenting a single endpoint 3204 + to accounts hosted on different JMAP servers (splitting the request 3205 + based on each method's "accountId" argument). The proxy need only 3206 + understand the general structure of a JMAP Request object; it does 3207 + not need to know anything specifically about the methods and 3208 + arguments it will pass through to other servers. 3209 + 3210 + If splitting up the methods in a request to call them on different 3211 + backend servers, the proxy must do two things to ensure back- 3212 + references and creation-id references resolve the same as if the 3213 + entire request were processed on a single server: 3214 + 3215 + 1. It must pass a "createdIds" property with each subrequest. If 3216 + this is not given by the client, an empty object should be used 3217 + for the first subrequest. The "createdIds" property of each 3218 + subresponse should be passed on in the next subrequest. 3219 + 3220 + 2. It must resolve back-references to previous method results that 3221 + were processed on a different server. This is a relatively 3222 + simple syntactic substitution, described in Section 3.7. 3223 + 3224 + When splitting a request based on accountId, proxy implementors do 3225 + need to be aware of "/copy" methods that copy between accounts. If 3226 + the accounts are on different servers, the proxy will have to 3227 + implement this functionality directly. 3228 + 3229 + 6. Binary Data 3230 + 3231 + Binary data is referenced by a *blobId* in JMAP and uploaded/ 3232 + downloaded separately to the core API. The blobId solely represents 3233 + the raw bytes of data, not any associated metadata such as a file 3234 + name or content type. Such metadata is stored alongside the blobId 3235 + in the object referencing it. The data represented by a blobId is 3236 + immutable. 3237 + 3238 + Any blobId that exists within an account may be used when creating/ 3239 + updating another object in that account. For example, an Email type 3240 + may have a blobId that represents the object in Internet Message 3241 + Format [RFC5322]. A client could create a new Email object with an 3242 + attachment and use this blobId, in effect attaching the old message 3243 + to the new one. Similarly, it could attach any existing attachment 3244 + of an old message without having to download and upload it again. 3245 + 3246 + 3247 + 3248 + 3249 + 3250 + Jenkins & Newman Standards Track [Page 58] 3251 + 3252 + RFC 8620 JMAP July 2019 3253 + 3254 + 3255 + When the client uses a blobId in a create/update, the server MAY 3256 + assign a new blobId to refer to the same binary data within the new/ 3257 + updated object. If it does so, it MUST return any properties that 3258 + contain a changed blobId in the created/updated response, so the 3259 + client gets the new ids. 3260 + 3261 + A blob that is not referenced by a JMAP object (e.g., as a message 3262 + attachment) MAY be deleted by the server to free up resources. 3263 + Uploads (see below) are initially unreferenced blobs. To ensure 3264 + interoperability: 3265 + 3266 + o The server SHOULD use a separate quota for unreferenced blobs to 3267 + the account's usual quota. In the case of shared accounts, this 3268 + quota SHOULD be separate per user. 3269 + 3270 + o This quota SHOULD be at least the maximum total size that a single 3271 + object can reference on this server. For example, if supporting 3272 + JMAP Mail, this should be at least the maximum total attachments 3273 + size for a message. 3274 + 3275 + o When an upload would take the user over quota, the server MUST 3276 + delete unreferenced blobs in date order, oldest first, until there 3277 + is room for the new blob. 3278 + 3279 + o Except where quota restrictions force early deletion, an 3280 + unreferenced blob MUST NOT be deleted for at least 1 hour from the 3281 + time of upload; if reuploaded, the same blobId MAY be returned, 3282 + but this SHOULD reset the expiry time. 3283 + 3284 + o A blob MUST NOT be deleted during the method call that removed the 3285 + last reference, so that a client can issue a create and a destroy 3286 + that both reference the blob within the same method call. 3287 + 3288 + 6.1. Uploading Binary Data 3289 + 3290 + There is a single endpoint that handles all file uploads for an 3291 + account, regardless of what they are to be used for. The Session 3292 + object (see Section 2) has an "uploadUrl" property in URI Template 3293 + (level 1) format [RFC6570], which MUST contain a variable called 3294 + "accountId". The client may use this template in combination with an 3295 + "accountId" to get the URL of the file upload resource. 3296 + 3297 + To upload a file, the client submits an authenticated POST request to 3298 + the file upload resource. 3299 + 3300 + 3301 + 3302 + 3303 + 3304 + 3305 + 3306 + Jenkins & Newman Standards Track [Page 59] 3307 + 3308 + RFC 8620 JMAP July 2019 3309 + 3310 + 3311 + A successful request MUST return a single JSON object with the 3312 + following properties as the response: 3313 + 3314 + o accountId: "Id" 3315 + 3316 + The id of the account used for the call. 3317 + 3318 + o blobId: "Id" 3319 + 3320 + The id representing the binary data uploaded. The data for this 3321 + id is immutable. The id *only* refers to the binary data, not any 3322 + metadata. 3323 + 3324 + o type: "String" 3325 + 3326 + The media type of the file (as specified in [RFC6838], 3327 + Section 4.2) as set in the Content-Type header of the upload HTTP 3328 + request. 3329 + 3330 + o size: "UnsignedInt" 3331 + 3332 + The size of the file in octets. 3333 + 3334 + If identical binary content to an existing blob in the account is 3335 + uploaded, the existing blobId MAY be returned. 3336 + 3337 + Clients should use the blobId returned in a timely manner. Under 3338 + rare circumstances, the server may have deleted the blob before the 3339 + client uses it; the client should keep a reference to the local file 3340 + so it can upload it again in such a situation. 3341 + 3342 + When an HTTP error response is returned to the client, the server 3343 + SHOULD return a JSON "problem details" object as the response body, 3344 + as per [RFC7807]. 3345 + 3346 + As access controls are often determined by the object holding the 3347 + reference to a blob, unreferenced blobs MUST only be accessible to 3348 + the uploader, even in shared accounts. 3349 + 3350 + 6.2. Downloading Binary Data 3351 + 3352 + The Session object (see Section 2) has a "downloadUrl" property, 3353 + which is in URI Template (level 1) format [RFC6570]. The URL MUST 3354 + contain variables called "accountId", "blobId", "type", and "name". 3355 + 3356 + 3357 + 3358 + 3359 + 3360 + 3361 + 3362 + Jenkins & Newman Standards Track [Page 60] 3363 + 3364 + RFC 8620 JMAP July 2019 3365 + 3366 + 3367 + To download a file, the client makes an authenticated GET request to 3368 + the download URL with the appropriate variables substituted in: 3369 + 3370 + o "accountId": The id of the account to which the record with the 3371 + blobId belongs. 3372 + 3373 + o "blobId": The blobId representing the data of the file to 3374 + download. 3375 + 3376 + o "type": The type for the server to set in the "Content-Type" 3377 + header of the response; the blobId only represents the binary data 3378 + and does not have a content-type innately associated with it. 3379 + 3380 + o "name": The name for the file; the server MUST return this as the 3381 + filename if it sets a "Content-Disposition" header. 3382 + 3383 + As the data for a particular blobId is immutable, and thus the 3384 + response in the generated download URL is too, implementors are 3385 + recommended to set long cache times and use the "immutable" Cache- 3386 + Control extension [RFC8246] for successful responses, for example, 3387 + "Cache-Control: private, immutable, max-age=31536000". 3388 + 3389 + When an HTTP error response is returned to the client, the server 3390 + SHOULD return a JSON "problem details" object as the response body, 3391 + as per [RFC7807]. 3392 + 3393 + 6.3. Blob/copy 3394 + 3395 + Binary data may be copied *between* two different accounts using the 3396 + "Blob/copy" method rather than having to download and then reupload 3397 + on the client. 3398 + 3399 + The "Blob/copy" method takes the following arguments: 3400 + 3401 + o fromAccountId: "Id" 3402 + 3403 + The id of the account to copy blobs from. 3404 + 3405 + o accountId: "Id" 3406 + 3407 + The id of the account to copy blobs to. 3408 + 3409 + o blobIds: "Id[]" 3410 + 3411 + A list of ids of blobs to copy to the other account. 3412 + 3413 + 3414 + 3415 + 3416 + 3417 + 3418 + Jenkins & Newman Standards Track [Page 61] 3419 + 3420 + RFC 8620 JMAP July 2019 3421 + 3422 + 3423 + The response has the following arguments: 3424 + 3425 + o fromAccountId: "Id" 3426 + 3427 + The id of the account blobs were copied from. 3428 + 3429 + o accountId: "Id" 3430 + 3431 + The id of the account blobs were copied to. 3432 + 3433 + o copied: "Id[Id]|null" 3434 + 3435 + A map of the blobId in the fromAccount to the id for the blob in 3436 + the account it was copied to, or null if none were successfully 3437 + copied. 3438 + 3439 + o notCopied: "Id[SetError]|null" 3440 + 3441 + A map of blobId to a SetError object for each blob that failed to 3442 + be copied, or null if none. 3443 + 3444 + The SetError may be any of the standard set errors that may be 3445 + returned for a create, as defined in Section 5.3. In addition, the 3446 + "notFound" SetError error may be returned if the blobId to be copied 3447 + cannot be found. 3448 + 3449 + The following additional method-level error may be returned instead 3450 + of the "Blob/copy" response: 3451 + 3452 + "fromAccountNotFound": The "fromAccountId" included with the request 3453 + does not correspond to a valid account. 3454 + 3455 + 7. Push 3456 + 3457 + Push notifications allow clients to efficiently update (almost) 3458 + instantly to stay in sync with data changes on the server. The 3459 + general model for push is simple and sends minimal data over the push 3460 + channel: just enough for the client to know whether it needs to 3461 + resync. The format allows multiple changes to be coalesced into a 3462 + single push update and the frequency of pushes to be rate limited by 3463 + the server. It doesn't matter if some push events are dropped before 3464 + they reach the client; the next time it gets/sets any records of a 3465 + changed type, it will discover the data has changed and still sync 3466 + all changes. 3467 + 3468 + 3469 + 3470 + 3471 + 3472 + 3473 + 3474 + Jenkins & Newman Standards Track [Page 62] 3475 + 3476 + RFC 8620 JMAP July 2019 3477 + 3478 + 3479 + There are two different mechanisms by which a client can receive push 3480 + notifications, to allow for the different environments in which a 3481 + client may exist. An event source resource (see Section 7.3) allows 3482 + clients that can hold transport connections open to receive push 3483 + notifications directly from the JMAP server. This is simple and 3484 + avoids third parties, but it is often not feasible on constrained 3485 + platforms such as mobile devices. Alternatively, clients can make 3486 + use of any push service supported by their environment. A URL for 3487 + the push service is registered with the JMAP server (see 3488 + Section 7.2); the server then POSTs each notification to that URL. 3489 + The push service is then responsible for routing these to the client. 3490 + 3491 + 7.1. The StateChange Object 3492 + 3493 + When something changes on the server, the server pushes a StateChange 3494 + object to the client. A *StateChange* object has the following 3495 + properties: 3496 + 3497 + o @type: "String" 3498 + 3499 + This MUST be the string "StateChange". 3500 + 3501 + o changed: "Id[TypeState]" 3502 + 3503 + A map of an "account id" to an object encoding the state of data 3504 + types that have changed for that account since the last 3505 + StateChange object was pushed, for each of the accounts to which 3506 + the user has access and for which something has changed. 3507 + 3508 + A *TypeState* object is a map. The keys are the type name "Foo" 3509 + (e.g., "Mailbox" or "Email"), and the value is the "state" 3510 + property that would currently be returned by a call to "Foo/get". 3511 + 3512 + The client can compare the new state strings with its current 3513 + values to see whether it has the current data for these types. If 3514 + not, the changes can then be efficiently fetched in a single 3515 + standard API request (using the /changes type methods). 3516 + 3517 + 3518 + 3519 + 3520 + 3521 + 3522 + 3523 + 3524 + 3525 + 3526 + 3527 + 3528 + 3529 + 3530 + Jenkins & Newman Standards Track [Page 63] 3531 + 3532 + RFC 8620 JMAP July 2019 3533 + 3534 + 3535 + 7.1.1. Example 3536 + 3537 + In this example, the server has amalgamated a few changes together 3538 + across two different accounts the user has access to, before pushing 3539 + the following StateChange object to the client: 3540 + 3541 + { 3542 + "@type": "StateChange", 3543 + "changed": { 3544 + "a3123": { 3545 + "Email": "d35ecb040aab", 3546 + "EmailDelivery": "428d565f2440", 3547 + "CalendarEvent": "87accfac587a" 3548 + }, 3549 + "a43461d": { 3550 + "Mailbox": "0af7a512ce70", 3551 + "CalendarEvent": "7a4297cecd76" 3552 + } 3553 + } 3554 + } 3555 + 3556 + The client can compare the state strings with its current state for 3557 + the Email, CalendarEvent, etc., object types in the appropriate 3558 + accounts to see if it needs to fetch changes. 3559 + 3560 + If the client is itself making changes, it may receive a StateChange 3561 + object while the /set API call is in flight. It can wait until the 3562 + call completes and then compare if the new state string after the 3563 + /set is the same as was pushed in the StateChange object; if so, and 3564 + the old state of the /set response matches the client's previous 3565 + state, it does not need to waste a request asking for changes it 3566 + already knows. 3567 + 3568 + 7.2. PushSubscription 3569 + 3570 + Clients may create a PushSubscription to register a URL with the JMAP 3571 + server. The JMAP server will then make an HTTP POST request to this 3572 + URL for each push notification it wishes to send to the client. 3573 + 3574 + As a push subscription causes the JMAP server to make a number of 3575 + requests to a previously unknown endpoint, it can be used as a vector 3576 + for launching a denial-of-service attack. To prevent this, when a 3577 + subscription is created, the JMAP server immediately sends a 3578 + PushVerification object to that URL (see Section 7.2.2). The JMAP 3579 + server MUST NOT make any further requests to the URL until the client 3580 + receives the push and updates the subscription with the correct 3581 + verification code. 3582 + 3583 + 3584 + 3585 + 3586 + Jenkins & Newman Standards Track [Page 64] 3587 + 3588 + RFC 8620 JMAP July 2019 3589 + 3590 + 3591 + A *PushSubscription* object has the following properties: 3592 + 3593 + o id: "Id" (immutable; server-set) 3594 + 3595 + The id of the push subscription. 3596 + 3597 + o deviceClientId: "String" (immutable) 3598 + 3599 + An id that uniquely identifies the client + device it is running 3600 + on. The purpose of this is to allow clients to identify which 3601 + PushSubscription objects they created even if they lose their 3602 + local state, so they can revoke or update them. This string MUST 3603 + be different on different devices and be different from apps from 3604 + other vendors. It SHOULD be easy to regenerate and not depend on 3605 + persisted state. It is RECOMMENDED to use a secure hash of a 3606 + string that contains: 3607 + 3608 + 1. A unique identifier associated with the device where the JMAP 3609 + client is running, normally supplied by the device's operating 3610 + system. 3611 + 3612 + 2. A custom vendor/app id, including a domain controlled by the 3613 + vendor of the JMAP client. 3614 + 3615 + To protect the privacy of the user, the deviceClientId id MUST NOT 3616 + contain an unobfuscated device id. 3617 + 3618 + o url: "String" (immutable) 3619 + 3620 + An absolute URL where the JMAP server will POST the data for the 3621 + push message. This MUST begin with "https://". 3622 + 3623 + o keys: "Object|null" (immutable) 3624 + 3625 + Client-generated encryption keys. If supplied, the server MUST 3626 + use them as specified in [RFC8291] to encrypt all data sent to the 3627 + push subscription. The object MUST have the following properties: 3628 + 3629 + * p256dh: "String" 3630 + 3631 + The P-256 Elliptic Curve Diffie-Hellman (ECDH) public key as 3632 + described in [RFC8291], encoded in URL-safe base64 3633 + representation as defined in [RFC4648]. 3634 + 3635 + * auth: "String" 3636 + 3637 + The authentication secret as described in [RFC8291], encoded in 3638 + URL-safe base64 representation as defined in [RFC4648]. 3639 + 3640 + 3641 + 3642 + Jenkins & Newman Standards Track [Page 65] 3643 + 3644 + RFC 8620 JMAP July 2019 3645 + 3646 + 3647 + o verificationCode: "String|null" 3648 + 3649 + This MUST be null (or omitted) when the subscription is created. 3650 + The JMAP server then generates a verification code and sends it in 3651 + a push message, and the client updates the PushSubscription object 3652 + with the code; see Section 7.2.2 for details. 3653 + 3654 + o expires: "UTCDate|null" 3655 + 3656 + The time this push subscription expires. If specified, the JMAP 3657 + server MUST NOT make further requests to this resource after this 3658 + time. It MAY automatically destroy the push subscription at or 3659 + after this time. 3660 + 3661 + The server MAY choose to set an expiry if none is given by the 3662 + client or modify the expiry time given by the client to a shorter 3663 + duration. 3664 + 3665 + o types: "String[]|null" 3666 + 3667 + A list of types the client is interested in (using the same names 3668 + as the keys in the TypeState object defined in the previous 3669 + section). A StateChange notification will only be sent if the 3670 + data for one of these types changes. Other types are omitted from 3671 + the TypeState object. If null, changes will be pushed for all 3672 + types. 3673 + 3674 + The POST request MUST have a content type of "application/json" and 3675 + contain the UTF-8 JSON-encoded object as the body. The request MUST 3676 + have a "TTL" header and MAY have "Urgency" and/or "Topic" headers, as 3677 + specified in Section 5 of [RFC8030]. The JMAP server is expected to 3678 + understand and handle HTTP status responses in a reasonable manner. 3679 + A "429" (Too Many Requests) response MUST cause the JMAP server to 3680 + reduce the frequency of pushes; the JMAP push structure allows 3681 + multiple changes to be coalesced into a single minimal StateChange 3682 + object. See the security considerations in Section 8.6 for a 3683 + discussion of the risks in connecting to unknown servers. 3684 + 3685 + The JMAP server acts as an application server as defined in 3686 + [RFC8030]. A client MAY use the rest of [RFC8030] in combination 3687 + with its own push service to form a complete end-to-end solution, or 3688 + it MAY rely on alternative mechanisms to ensure the delivery of the 3689 + pushed data after it leaves the JMAP server. 3690 + 3691 + The push subscription is tied to the credentials used to authenticate 3692 + the API request that created it. Should these credentials expire or 3693 + be revoked, the push subscription MUST be destroyed by the JMAP 3694 + 3695 + 3696 + 3697 + 3698 + Jenkins & Newman Standards Track [Page 66] 3699 + 3700 + RFC 8620 JMAP July 2019 3701 + 3702 + 3703 + server. Only subscriptions created by these credentials are returned 3704 + when the client fetches existing subscriptions. 3705 + 3706 + When these credentials have their own expiry (i.e., it is a session 3707 + with a timeout), the server SHOULD NOT set or bound the expiry time 3708 + for the push subscription given by the client but MUST expire it when 3709 + the session expires. 3710 + 3711 + When these credentials are not time bounded (e.g., Basic 3712 + authentication [RFC7617]), the server SHOULD set an expiry time for 3713 + the push subscription if none is given and limit the expiry time if 3714 + set too far in the future. This maximum expiry time MUST be at least 3715 + 48 hours in the future and SHOULD be at least 7 days in the future. 3716 + An app running on a mobile device may only be able to refresh the 3717 + push subscription lifetime when it is in the foreground, so this 3718 + gives a reasonable time frame to allow this to happen. 3719 + 3720 + In the case of separate access and refresh credentials, as in Oauth 3721 + 2.0 [RFC6749], the server SHOULD tie the push subscription to the 3722 + validity of the refresh token rather than the access token and behave 3723 + according to whether this is time-limited or not. 3724 + 3725 + When a push subscription is destroyed, the server MUST securely erase 3726 + the URL and encryption keys from memory and storage as soon as 3727 + possible. 3728 + 3729 + 7.2.1. PushSubscription/get 3730 + 3731 + Standard /get method as described in Section 5.1, except it does 3732 + *not* take or return an "accountId" argument, as push subscriptions 3733 + are not tied to specific accounts. It also does *not* return a 3734 + "state" argument. The "ids" argument may be null to fetch all at 3735 + once. 3736 + 3737 + The server MUST only return push subscriptions that were created 3738 + using the same authentication credentials as for this 3739 + "PushSubscription/get" request. 3740 + 3741 + As the "url" and "keys" properties may contain data that is private 3742 + to a particular device, the values for these properties MUST NOT be 3743 + returned. If the "properties" argument is null or omitted, the 3744 + server MUST default to all properties excluding these two. If one of 3745 + them is explicitly requested, the method call MUST be rejected with a 3746 + "forbidden" error. 3747 + 3748 + 3749 + 3750 + 3751 + 3752 + 3753 + 3754 + Jenkins & Newman Standards Track [Page 67] 3755 + 3756 + RFC 8620 JMAP July 2019 3757 + 3758 + 3759 + 7.2.2. PushSubscription/set 3760 + 3761 + Standard /set method as described in Section 5.3, except it does 3762 + *not* take or return an "accountId" argument, as push subscriptions 3763 + are not tied to specific accounts. It also does *not* take an 3764 + "ifInState" argument or return "oldState" or "newState" arguments. 3765 + 3766 + The "url" and "keys" properties are immutable; if the client wishes 3767 + to change these, it must destroy the current push subscription and 3768 + create a new one. 3769 + 3770 + When a PushSubscription is created, the server MUST immediately push 3771 + a *PushVerification* object to the URL. It has the following 3772 + properties: 3773 + 3774 + o @type: "String" 3775 + 3776 + This MUST be the string "PushVerification". 3777 + 3778 + o pushSubscriptionId: "String" 3779 + 3780 + The id of the push subscription that was created. 3781 + 3782 + o verificationCode: "String" 3783 + 3784 + The verification code to add to the push subscription. This MUST 3785 + contain sufficient entropy to avoid the client being able to guess 3786 + the code via brute force. 3787 + 3788 + The client MUST update the push subscription with the correct 3789 + verification code before the server makes any further requests to the 3790 + subscription's URL. Attempts to update the subscription with an 3791 + invalid verification code MUST be rejected by the server with an 3792 + "invalidProperties" SetError. 3793 + 3794 + The client may update the "expires" property to extend (or, less 3795 + commonly, shorten) the lifetime of a push subscription. The server 3796 + MAY modify the proposed new expiry time to enforce server-defined 3797 + limits. Extending the lifetime does not require the subscription to 3798 + be verified again. 3799 + 3800 + Clients SHOULD NOT update or destroy a push subscription that they 3801 + did not create (i.e., has a "deviceClientId" that they do not 3802 + recognise). 3803 + 3804 + 3805 + 3806 + 3807 + 3808 + 3809 + 3810 + Jenkins & Newman Standards Track [Page 68] 3811 + 3812 + RFC 8620 JMAP July 2019 3813 + 3814 + 3815 + 7.2.3. Example 3816 + 3817 + At "2018-07-06T02:14:29Z", a client with deviceClientId "a889-ffea- 3818 + 910" fetches the set of push subscriptions currently on the server, 3819 + making an API request with: 3820 + 3821 + [[ "PushSubscription/get", { 3822 + "ids": null 3823 + }, "0" ]] 3824 + 3825 + Which returns: 3826 + 3827 + [[ "PushSubscription/get", { 3828 + "list": [{ 3829 + "id": "e50b2c1d-9553-41a3-b0a7-a7d26b599ee1", 3830 + "deviceClientId": "b37ff8001ca0", 3831 + "verificationCode": "b210ef734fe5f439c1ca386421359f7b", 3832 + "expires": "2018-07-31T00:13:21Z", 3833 + "types": [ "Todo" ] 3834 + }, { 3835 + "id": "f2d0aab5-e976-4e8b-ad4b-b380a5b987e4", 3836 + "deviceClientId": "X8980fc", 3837 + "verificationCode": "f3d4618a9ae15c8b7f5582533786d531", 3838 + "expires": "2018-07-12T05:55:00Z", 3839 + "types": [ "Mailbox", "Email", "EmailDelivery" ] 3840 + }], 3841 + "notFound": [] 3842 + }, "0" ]] 3843 + 3844 + Since neither of the returned push subscription objects have the 3845 + client's deviceClientId, it knows it does not have a current push 3846 + subscription active on the server. So it creates one, sending this 3847 + request: 3848 + 3849 + [[ "PushSubscription/set", { 3850 + "create": { 3851 + "4f29": { 3852 + "deviceClientId": "a889-ffea-910", 3853 + "url": "https://example.com/push/?device=X8980fc&client=12c6d086", 3854 + "types": null 3855 + } 3856 + } 3857 + }, "0" ]] 3858 + 3859 + 3860 + 3861 + 3862 + 3863 + 3864 + 3865 + 3866 + Jenkins & Newman Standards Track [Page 69] 3867 + 3868 + RFC 8620 JMAP July 2019 3869 + 3870 + 3871 + The server creates the push subscription but limits the expiry time 3872 + to 7 days in the future, returning this response: 3873 + 3874 + [[ "PushSubscription/set", { 3875 + "created": { 3876 + "4f29": { 3877 + "id": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60", 3878 + "keys": null, 3879 + "expires": "2018-07-13T02:14:29Z" 3880 + } 3881 + } 3882 + }, "0" ]] 3883 + 3884 + The server also immediately makes a POST request to 3885 + "https://example.com/push/?device=X8980fc&client=12c6d086" with the 3886 + data: 3887 + 3888 + { 3889 + "@type": "PushVerification", 3890 + "pushSubscriptionId": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60", 3891 + "verificationCode": "da1f097b11ca17f06424e30bf02bfa67" 3892 + } 3893 + 3894 + The client receives this and updates the subscription with the 3895 + verification code (note there is a potential race condition here; the 3896 + client MUST be able to handle receiving the push while the request 3897 + creating the subscription is still in progress): 3898 + 3899 + [[ "PushSubscription/set", { 3900 + "update": { 3901 + "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": { 3902 + "verificationCode": "da1f097b11ca17f06424e30bf02bfa67" 3903 + } 3904 + } 3905 + }, "0" ]] 3906 + 3907 + The server confirms the update was successful and will now make 3908 + requests to the registered URL when the state changes. 3909 + 3910 + 3911 + 3912 + 3913 + 3914 + 3915 + 3916 + 3917 + 3918 + 3919 + 3920 + 3921 + 3922 + Jenkins & Newman Standards Track [Page 70] 3923 + 3924 + RFC 8620 JMAP July 2019 3925 + 3926 + 3927 + Two days later, the client updates the subscription to extend its 3928 + lifetime, sending this request: 3929 + 3930 + [[ "PushSubscription/set", { 3931 + "update": { 3932 + "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": { 3933 + "expires": "2018-08-13T00:00:00Z" 3934 + } 3935 + } 3936 + }, "0" ]] 3937 + 3938 + The server extends the expiry time, but only again to its maximum 3939 + limit of 7 days in the future, returning this response: 3940 + 3941 + [[ "PushSubscription/set", { 3942 + "updated": { 3943 + "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": { 3944 + "expires": "2018-07-15T02:22:50Z" 3945 + } 3946 + } 3947 + }, "0" ]] 3948 + 3949 + 7.3. Event Source 3950 + 3951 + Clients that can hold transport connections open can connect directly 3952 + to the JMAP server to receive push notifications via a "text/event- 3953 + stream" resource, as described in [EventSource]. This is a long 3954 + running HTTP request, where the server can push data to the client by 3955 + appending data without ending the response. 3956 + 3957 + When a change occurs in the data on the server, it pushes an event 3958 + called "state" to any connected clients, with the StateChange object 3959 + as the data. 3960 + 3961 + The server SHOULD also send a new event id that encodes the entire 3962 + server state visible to the user immediately after sending a "state" 3963 + event. When a new connection is made to the event-source endpoint, a 3964 + client following the server-sent events specification will send a 3965 + Last-Event-ID HTTP header field with the last id it saw, which the 3966 + server can use to work out whether the client has missed some 3967 + changes. If so, it SHOULD send these changes immediately on 3968 + connection. 3969 + 3970 + The Session object (see Section 2) has an "eventSourceUrl" property, 3971 + which is in URI Template (level 1) format [RFC6570]. The URL MUST 3972 + contain variables called "types", "closeafter", and "ping". 3973 + 3974 + 3975 + 3976 + 3977 + 3978 + Jenkins & Newman Standards Track [Page 71] 3979 + 3980 + RFC 8620 JMAP July 2019 3981 + 3982 + 3983 + To connect to the resource, the client makes an authenticated GET 3984 + request to the event-source URL with the appropriate variables 3985 + substituted in: 3986 + 3987 + o "types": This MUST be either: 3988 + 3989 + * A comma-separated list of type names, e.g., 3990 + "Email,CalendarEvent". The server MUST only push changes for 3991 + the types in this list. 3992 + 3993 + * The single character: "*". Changes to all types are pushed. 3994 + 3995 + o "closeafter": This MUST be one of the following values: 3996 + 3997 + * "state": The server MUST end the HTTP response after pushing a 3998 + state event. This can be used by clients in environments where 3999 + buffering proxies prevent the pushed data from arriving 4000 + immediately, or indeed at all, when operating in the usual 4001 + mode. 4002 + 4003 + * "no": The connection is persisted by the server as a standard 4004 + event-source resource. 4005 + 4006 + o "ping": A positive integer value representing a length of time in 4007 + seconds, e.g., "300". If non-zero, the server MUST send an event 4008 + called "ping" whenever this time elapses since the previous event 4009 + was sent. This MUST NOT set a new event id. If the value is "0", 4010 + the server MUST NOT send ping events. 4011 + 4012 + The server MAY modify a requested ping interval to be subject to a 4013 + minimum and/or maximum value. For interoperability, servers MUST 4014 + NOT have a minimum allowed value higher than 30 or a maximum 4015 + allowed value less than 300. 4016 + 4017 + The data for the ping event MUST be a JSON object containing an 4018 + "interval" property, the value (type "UnsignedInt") being the 4019 + interval in seconds the server is using to send pings (this may be 4020 + different to the requested value if the server clamped it to be 4021 + within a min/max value). 4022 + 4023 + Clients can monitor for the ping event to help determine when the 4024 + closeafter mode may be required. 4025 + 4026 + A client MAY hold open multiple connections to the event-source 4027 + resource, although it SHOULD try to use a single connection for 4028 + efficiency. 4029 + 4030 + 4031 + 4032 + 4033 + 4034 + Jenkins & Newman Standards Track [Page 72] 4035 + 4036 + RFC 8620 JMAP July 2019 4037 + 4038 + 4039 + 8. Security Considerations 4040 + 4041 + 8.1. Transport Confidentiality 4042 + 4043 + To ensure the confidentiality and integrity of data sent and received 4044 + via JMAP, all requests MUST use TLS 1.2 [RFC5246] [RFC8446] or later, 4045 + following the recommendations in [RFC7525]. Servers SHOULD support 4046 + TLS 1.3 [RFC8446] or later. 4047 + 4048 + Clients MUST validate TLS certificate chains to protect against 4049 + man-in-the-middle attacks [RFC5280]. 4050 + 4051 + 8.2. Authentication Scheme 4052 + 4053 + A number of HTTP authentication schemes have been standardised (see 4054 + <https://www.iana.org/assignments/http-authschemes/>). Servers 4055 + should take care to assess the security characteristics of different 4056 + schemes in relation to their needs when deciding what to implement. 4057 + 4058 + Use of the Basic authentication scheme is NOT RECOMMENDED. Services 4059 + that choose to use it are strongly recommended to require generation 4060 + of a unique "app password" via some external mechanism for each 4061 + client they wish to connect. This allows connections from different 4062 + devices to be differentiated by the server and access to be 4063 + individually revoked. 4064 + 4065 + 8.3. Service Autodiscovery 4066 + 4067 + Unless secured by something like DNSSEC, autodiscovery of server 4068 + details using SRV DNS records is vulnerable to a DNS poisoning 4069 + attack, which can lead to the client talking to an attacker's server 4070 + instead of the real JMAP server. The attacker may then intercept 4071 + requests to execute man-in-the-middle attacks and, depending on the 4072 + authentication scheme, steal credentials to generate its own 4073 + requests. 4074 + 4075 + Clients that do not support SRV lookups are likely to try just using 4076 + the "/.well-known/jmap" path directly against the domain of the 4077 + username over HTTPS. Servers SHOULD ensure this path resolves or 4078 + redirects to the correct JMAP Session resource to allow this to work. 4079 + If this is not feasible, servers MUST ensure this path cannot be 4080 + controlled by an attacker, as again it may be used to steal 4081 + credentials. 4082 + 4083 + 4084 + 4085 + 4086 + 4087 + 4088 + 4089 + 4090 + Jenkins & Newman Standards Track [Page 73] 4091 + 4092 + RFC 8620 JMAP July 2019 4093 + 4094 + 4095 + 8.4. JSON Parsing 4096 + 4097 + The Security Considerations of [RFC8259] apply to the use of JSON as 4098 + the data interchange format. 4099 + 4100 + As for any serialization format, parsers need to thoroughly check the 4101 + syntax of the supplied data. JSON uses opening and closing tags for 4102 + several types and structures, and it is possible that the end of the 4103 + supplied data will be reached when scanning for a matching closing 4104 + tag; this is an error condition, and implementations need to stop 4105 + scanning at the end of the supplied data. 4106 + 4107 + JSON also uses a string encoding with some escape sequences to encode 4108 + special characters within a string. Care is needed when processing 4109 + these escape sequences to ensure that they are fully formed before 4110 + the special processing is triggered, with special care taken when the 4111 + escape sequences appear adjacent to other (non-escaped) special 4112 + characters or adjacent to the end of data (as in the previous 4113 + paragraph). 4114 + 4115 + If parsing JSON into a non-textual structured data format, 4116 + implementations may need to allocate storage to hold JSON string 4117 + elements. Since JSON does not use explicit string lengths, the risk 4118 + of denial of service due to resource exhaustion is small, but 4119 + implementations may still wish to place limits on the size of 4120 + allocations they are willing to make in any given context, to avoid 4121 + untrusted data causing excessive memory allocation. 4122 + 4123 + 8.5. Denial of Service 4124 + 4125 + A small request may result in a very large response and require 4126 + considerable work on the server if resource limits are not enforced. 4127 + JMAP provides mechanisms for advertising and enforcing a wide variety 4128 + of limits for mitigating this threat, including limits on the number 4129 + of objects fetched in a single method call, number of methods in a 4130 + single request, number of concurrent requests, etc. 4131 + 4132 + JMAP servers MUST implement sensible limits to mitigate against 4133 + resource exhaustion attacks. 4134 + 4135 + 8.6. Connection to Unknown Push Server 4136 + 4137 + When a push subscription is registered, the application server will 4138 + make POST requests to the given URL. There are a number of security 4139 + considerations that MUST be considered when implementing this. 4140 + 4141 + 4142 + 4143 + 4144 + 4145 + 4146 + Jenkins & Newman Standards Track [Page 74] 4147 + 4148 + RFC 8620 JMAP July 2019 4149 + 4150 + 4151 + The server MUST ensure the URL is externally resolvable to avoid 4152 + server-side request forgery, where the server makes a request to a 4153 + resource on its internal network. 4154 + 4155 + A malicious client may use the push subscription to attempt to flood 4156 + a third party server with requests, creating a denial-of-service 4157 + attack and masking the attacker's true identity. There is no 4158 + guarantee that the URL given to the JMAP server is actually a valid 4159 + push server. Upon creation of a push subscription, the JMAP server 4160 + sends a PushVerification object to the URL and MUST NOT send any 4161 + further requests until the client verifies it has received the 4162 + initial push. The verification code MUST contain sufficient entropy 4163 + to prevent the client from being able to verify the subscription via 4164 + brute force. 4165 + 4166 + The verification code does not guarantee the URL is a valid push 4167 + server, only that the client is able to access the data submitted to 4168 + it. While the verification step significantly reduces the set of 4169 + potential targets, there is still a risk that the server is unrelated 4170 + to the client and being targeted for a denial-of-service attack. 4171 + 4172 + The server MUST limit the number of push subscriptions any one user 4173 + may have to ensure the user cannot cause the server to send a large 4174 + number of push notifications at once, which could again be used as 4175 + part of a denial-of-service attack. The rate of creation MUST also 4176 + be limited to minimise the ability to abuse the verification request 4177 + as an attack vector. 4178 + 4179 + 8.7. Push Encryption 4180 + 4181 + When data changes, a small object is pushed with the new state 4182 + strings for the types that have changed. While the data here is 4183 + minimal, a passive man-in-the-middle attacker may be able to gain 4184 + useful information. To ensure confidentiality and integrity, if the 4185 + push is sent via a third party outside of the control of the client 4186 + and JMAP server, the client MUST specify encryption keys when 4187 + establishing the PushSubscription and ignore any push notification 4188 + received that is not encrypted with those keys. 4189 + 4190 + The privacy and security considerations of [RFC8030] and [RFC8291] 4191 + also apply to the use of the PushSubscription mechanism. 4192 + 4193 + As there is no crypto algorithm agility in Web Push Encryption 4194 + [RFC8291], a new specification will be needed to provide this if new 4195 + algorithms are required in the future. 4196 + 4197 + 4198 + 4199 + 4200 + 4201 + 4202 + Jenkins & Newman Standards Track [Page 75] 4203 + 4204 + RFC 8620 JMAP July 2019 4205 + 4206 + 4207 + 8.8. Traffic Analysis 4208 + 4209 + While the data is encrypted, a passive observer with the ability to 4210 + monitor network traffic may be able to glean information from the 4211 + timing of API requests and push notifications. For example, suppose 4212 + an email or calendar invitation is sent from User A (hosted on Server 4213 + X) to User B (hosted on Server Y). If Server X hosts data for many 4214 + users, a passive observer can see that the two servers connected but 4215 + does not know who the data was for. However, if a push notification 4216 + is immediately sent to User B and the attacker can observe this as 4217 + well, they may reasonably conclude that someone on Server X is 4218 + connecting to User B. 4219 + 4220 + 9. IANA Considerations 4221 + 4222 + 9.1. Assignment of jmap Service Name 4223 + 4224 + IANA has assigned the 'jmap' service name in the "Service Name and 4225 + Transport Protocol Port Number Registry" [RFC6335]. 4226 + 4227 + Service Name: jmap 4228 + 4229 + Transport Protocol(s): tcp 4230 + 4231 + Assignee: IESG 4232 + 4233 + Contact: IETF Chair 4234 + 4235 + Description: JSON Meta Application Protocol 4236 + 4237 + Reference: RFC 8620 4238 + 4239 + Assignment Notes: This service name was previously assigned under the 4240 + name "JSON Mail Access Protocol". This has been de-assigned and 4241 + re-assigned with the approval of the previous assignee. 4242 + 4243 + 9.2. Registration of Well-Known URI Suffix for JMAP 4244 + 4245 + IANA has registered the following suffix in the "Well-Known URIs" 4246 + registry for JMAP, as described in [RFC8615]: 4247 + 4248 + URI Suffix: jmap 4249 + 4250 + Change Controller: IETF 4251 + 4252 + Specification Document: RFC 8620, Section 2.2. 4253 + 4254 + 4255 + 4256 + 4257 + 4258 + Jenkins & Newman Standards Track [Page 76] 4259 + 4260 + RFC 8620 JMAP July 2019 4261 + 4262 + 4263 + 9.3. Registration of the jmap URN Sub-namespace 4264 + 4265 + IANA has registered the following URN sub-namespace in the "IETF URN 4266 + Sub-namespace for Registered Protocol Parameter Identifiers" registry 4267 + within the "Uniform Resource Name (URN) Namespace for IETF Use" 4268 + registry as described in [RFC3553]. 4269 + 4270 + Registered Parameter Identifier: jmap 4271 + 4272 + Reference: RFC 8620, Section 9.4 4273 + 4274 + IANA Registry Reference: http://www.iana.org/assignments/jmap 4275 + 4276 + 9.4. Creation of "JMAP Capabilities" Registry 4277 + 4278 + IANA has created the "JMAP Capabilities" registry as described in 4279 + Section 2. JMAP capabilities are advertised in the "capabilities" 4280 + property of the JMAP Session resource. They are used to extend the 4281 + functionality of a JMAP server. A capability is referenced by a URI. 4282 + The JMAP capability URI can be a URN starting with 4283 + "urn:ietf:params:jmap:" plus a unique suffix that is the index value 4284 + in the jmap URN sub-namespace. Registration of a JMAP capability 4285 + with another form of URI has no impact on the jmap URN sub-namespace. 4286 + 4287 + This registry follows the expert review process unless the "intended 4288 + use" field is "common" or "placeholder", in which case registration 4289 + follows the specification required process. 4290 + 4291 + A JMAP capability registration can have an intended use of "common", 4292 + "placeholder", "limited", or "obsolete". IANA will list common-use 4293 + registrations prominently and separately from those with other 4294 + intended use values. 4295 + 4296 + The JMAP capability registration procedure is not a formal standards 4297 + process but rather an administrative procedure intended to allow 4298 + community comment and sanity checking without excessive time delay. 4299 + 4300 + A "placeholder" registration reserves part of the jmap URN namespace 4301 + for another purpose but is typically not included in the 4302 + "capabilities" property of the JMAP Session resource. 4303 + 4304 + 9.4.1. Preliminary Community Review 4305 + 4306 + Notice of a potential JMAP common-use registration SHOULD be sent to 4307 + the JMAP mailing list <jmap@ietf.org> for review. This mailing list 4308 + is appropriate to solicit community feedback on a proposed JMAP 4309 + 4310 + 4311 + 4312 + 4313 + 4314 + Jenkins & Newman Standards Track [Page 77] 4315 + 4316 + RFC 8620 JMAP July 2019 4317 + 4318 + 4319 + capability. Registrations that are not intended for common use MAY 4320 + be sent to the list for review as well; doing so is entirely 4321 + OPTIONAL, but is encouraged. 4322 + 4323 + The intent of the public posting to this list is to solicit comments 4324 + and feedback on the choice of the capability name, the unambiguity of 4325 + the specification document, and a review of any interoperability or 4326 + security considerations. The submitter may submit a revised 4327 + registration proposal or abandon the registration completely at any 4328 + time. 4329 + 4330 + 9.4.2. Submit Request to IANA 4331 + 4332 + Registration requests can be sent to <iana@iana.org>. 4333 + 4334 + 9.4.3. Designated Expert Review 4335 + 4336 + For a limited-use registration, the primary concern of the designated 4337 + expert (DE) is preventing name collisions and encouraging the 4338 + submitter to document security and privacy considerations; a 4339 + published specification is not required. For a common-use 4340 + registration, the DE is expected to confirm that suitable 4341 + documentation, as described in Section 4.6 of [RFC8126], is 4342 + available. The DE should also verify that the capability does not 4343 + conflict with work that is active or already published within the 4344 + IETF. 4345 + 4346 + Before a period of 30 days has passed, the DE will either approve or 4347 + deny the registration request and publish a notice of the decision to 4348 + the JMAP WG mailing list or its successor, as well as inform IANA. A 4349 + denial notice must be justified by an explanation, and, in the cases 4350 + where it is possible, concrete suggestions on how the request can be 4351 + modified so as to become acceptable should be provided. 4352 + 4353 + If the DE does not respond within 30 days, the registrant may request 4354 + the IESG take action to process the request in a timely manner. 4355 + 4356 + 9.4.4. Change Procedures 4357 + 4358 + Once a JMAP capability has been published by the IANA, the change 4359 + controller may request a change to its definition. The same 4360 + procedure that would be appropriate for the original registration 4361 + request is used to process a change request. 4362 + 4363 + JMAP capability registrations may not be deleted; capabilities that 4364 + are no longer believed appropriate for use can be declared obsolete 4365 + by a change to their "intended use" field; such capabilities will be 4366 + clearly marked in the lists published by the IANA. 4367 + 4368 + 4369 + 4370 + Jenkins & Newman Standards Track [Page 78] 4371 + 4372 + RFC 8620 JMAP July 2019 4373 + 4374 + 4375 + Significant changes to a capability's definition should be requested 4376 + only when there are serious omissions or errors in the published 4377 + specification. When review is required, a change request may be 4378 + denied if it renders entities that were valid under the previous 4379 + definition invalid under the new definition. 4380 + 4381 + The owner of a JMAP capability may pass responsibility to another 4382 + person or agency by informing the IANA; this can be done without 4383 + discussion or review. 4384 + 4385 + The IESG may reassign responsibility for a JMAP capability. The most 4386 + common case of this will be to enable changes to be made to 4387 + capabilities where the author of the registration has died, moved out 4388 + of contact, or is otherwise unable to make changes that are important 4389 + to the community. 4390 + 4391 + 9.4.5. JMAP Capabilities Registry Template 4392 + 4393 + Capability name: (see capability property in Section 2) 4394 + 4395 + Specification document: 4396 + 4397 + Intended use: (one of common, limited, placeholder, or obsolete) 4398 + 4399 + Change controller: ("IETF" for Standards Track / BCP RFCs) 4400 + 4401 + Security and privacy considerations: 4402 + 4403 + 9.4.6. Initial Registration for JMAP Core 4404 + 4405 + Capability Name: "urn:ietf:params:jmap:core" 4406 + 4407 + Specification document: RFC 8620, Section 2 4408 + 4409 + Intended use: common 4410 + 4411 + Change Controller: IETF 4412 + 4413 + Security and privacy considerations: RFC 8620, Section 8. 4414 + 4415 + 4416 + 4417 + 4418 + 4419 + 4420 + 4421 + 4422 + 4423 + 4424 + 4425 + 4426 + Jenkins & Newman Standards Track [Page 79] 4427 + 4428 + RFC 8620 JMAP July 2019 4429 + 4430 + 4431 + 9.4.7. Registration for JMAP Error Placeholder in JMAP Capabilities 4432 + Registry 4433 + 4434 + Capability Name: "urn:ietf:params:jmap:error:" 4435 + 4436 + Specification document: RFC 8620, Section 9.5 4437 + 4438 + Intended use: placeholder 4439 + 4440 + Change Controller: IETF 4441 + 4442 + Security and privacy considerations: RFC 8620, Section 8. 4443 + 4444 + 9.5. Creation of "JMAP Error Codes" Registry 4445 + 4446 + IANA has created the "JMAP Error Codes" registry. JMAP error codes 4447 + appear in the "type" member of a JSON problem details object (as 4448 + described in Section 3.6.1), the "type" member in a JMAP error object 4449 + (as described in Section 3.6.2), or the "type" member of a JMAP 4450 + method-specific error object (such as SetError in Section 5.3). When 4451 + used in a problem details object, the prefix 4452 + "urn:ietf:params:jmap:error:" is always included; when used in JMAP 4453 + objects, the prefix is always omitted. 4454 + 4455 + This registry follows the expert review process. Preliminary 4456 + community review for this registry follows the same procedures as the 4457 + "JMAP Capabilities" registry, but it is optional. The change 4458 + procedures for this registry are the same as the change procedures 4459 + for the "JMAP Capabilities" registry. 4460 + 4461 + 9.5.1. Expert Review 4462 + 4463 + The designated expert should review the following aspects of the 4464 + registration: 4465 + 4466 + 1. Verify the error code does not conflict with existing names. 4467 + 4468 + 2. Verify the error code follows the syntax limitations (does not 4469 + require URI encoding). 4470 + 4471 + 3. Encourage the submitter to follow the naming convention of 4472 + previously registered errors. 4473 + 4474 + 4. Encourage the submitter to describe client behaviours that are 4475 + recommended in response to the error code. These may distinguish 4476 + the error code from other error codes. 4477 + 4478 + 4479 + 4480 + 4481 + 4482 + Jenkins & Newman Standards Track [Page 80] 4483 + 4484 + RFC 8620 JMAP July 2019 4485 + 4486 + 4487 + 5. Encourage the submitter to describe when the server should issue 4488 + the error as opposed to some other error code. 4489 + 4490 + 6. Encourage the submitter to note any security considerations 4491 + associated with the error, if any (e.g., an error code that might 4492 + disclose existence of data the authenticated user does not have 4493 + permission to know about). 4494 + 4495 + Steps 3-6 are meant to promote a higher-quality registry. However, 4496 + the expert is encouraged to approve any registration that would not 4497 + actively harm JMAP interoperability to make this a relatively 4498 + lightweight process. 4499 + 4500 + 9.5.2. JMAP Error Codes Registry Template 4501 + 4502 + JMAP Error Code: 4503 + 4504 + Intended use: (one of "common", "limited", "obsolete") 4505 + 4506 + Change Controller: ("IETF" for Standards Track / BCP RFCs) 4507 + 4508 + Reference: (Optional. Only required if defined in an RFC.) 4509 + 4510 + Description: 4511 + 4512 + 9.5.3. Initial Contents for the JMAP Error Codes Registry 4513 + 4514 + o JMAP Error Code: accountNotFound 4515 + Intended Use: Common 4516 + Change Controller: IETF 4517 + Reference: RFC 8620, Section 3.6.2 4518 + Description: The accountId does not correspond to a valid account. 4519 + 4520 + o JMAP Error Code: accountNotSupportedByMethod 4521 + Intended Use: Common 4522 + Change Controller: IETF 4523 + Reference: RFC 8620, Section 3.6.2 4524 + Description: The accountId given corresponds to a valid account, 4525 + but the account does not support this method or data type. 4526 + 4527 + o JMAP Error Code: accountReadOnly 4528 + Intended Use: Common 4529 + Change Controller: IETF 4530 + Reference: RFC 8620, Section 3.6.2 4531 + Description: This method modifies state, but the account is read- 4532 + only (as returned on the corresponding Account object in the JMAP 4533 + Session resource). 4534 + 4535 + 4536 + 4537 + 4538 + Jenkins & Newman Standards Track [Page 81] 4539 + 4540 + RFC 8620 JMAP July 2019 4541 + 4542 + 4543 + o JMAP Error Code: anchorNotFound 4544 + Intended Use: Common 4545 + Change Controller: IETF 4546 + Reference: RFC 8620, Section 5.5 4547 + Description: An anchor argument was supplied, but it cannot be 4548 + found in the results of the query. 4549 + 4550 + o JMAP Error Code: alreadyExists 4551 + Intended Use: Common 4552 + Change Controller: IETF 4553 + Reference: RFC 8620, Section 5.4 4554 + Description: The server forbids duplicates, and the record already 4555 + exists in the target account. An existingId property of type Id 4556 + MUST be included on the SetError object with the id of the 4557 + existing record. 4558 + 4559 + o JMAP Error Code: cannotCalculateChanges 4560 + Intended Use: Common 4561 + Change Controller: IETF 4562 + Reference: RFC 8620, Sections 5.2 and 5.6 4563 + Description: The server cannot calculate the changes from the 4564 + state string given by the client. 4565 + 4566 + o JMAP Error Code: forbidden 4567 + Intended Use: Common 4568 + Change Controller: IETF 4569 + Reference: RFC 8620, Sections 3.6.2, 5.3, and 7.2.1 4570 + Description: The action would violate an ACL or other permissions 4571 + policy. 4572 + 4573 + o JMAP Error Code: fromAccountNotFound 4574 + Intended Use: Common 4575 + Change Controller: IETF 4576 + Reference: RFC 8620, Sections 5.4 and 6.3 4577 + Description: The fromAccountId does not correspond to a valid 4578 + account. 4579 + 4580 + o JMAP Error Code: fromAccountNotSupportedByMethod 4581 + Intended Use: Common 4582 + Change Controller: IETF 4583 + Reference: RFC 8620, Section 5.4 4584 + Description: The fromAccountId given corresponds to a valid 4585 + account, but the account does not support this data type. 4586 + 4587 + 4588 + 4589 + 4590 + 4591 + 4592 + 4593 + 4594 + Jenkins & Newman Standards Track [Page 82] 4595 + 4596 + RFC 8620 JMAP July 2019 4597 + 4598 + 4599 + o JMAP Error Code: invalidArguments 4600 + Intended Use: Common 4601 + Change Controller: IETF 4602 + Reference: RFC 8620, Section 3.6.2 4603 + Description: One of the arguments is of the wrong type or 4604 + otherwise invalid, or a required argument is missing. 4605 + 4606 + o JMAP Error Code: invalidPatch 4607 + Intended Use: Common 4608 + Change Controller: IETF 4609 + Reference: RFC 8620, Section 5.3 4610 + Description: The PatchObject given to update the record was not a 4611 + valid patch. 4612 + 4613 + o JMAP Error Code: invalidProperties 4614 + Intended Use: Common 4615 + Change Controller: IETF 4616 + Reference: RFC 8620, Section 5.3 4617 + Description: The record given is invalid. 4618 + 4619 + o JMAP Error Code: notFound 4620 + Intended Use: Common 4621 + Change Controller: IETF 4622 + Reference: RFC 8620, Section 5.3 4623 + Description: The id given cannot be found. 4624 + 4625 + o JMAP Error Code: notJSON 4626 + Intended Use: Common 4627 + Change Controller: IETF 4628 + Reference: RFC 8620, Section 3.6.1 4629 + Description: The content type of the request was not application/ 4630 + json, or the request did not parse as I-JSON. 4631 + 4632 + o JMAP Error Code: notRequest 4633 + Intended Use: Common 4634 + Change Controller: IETF 4635 + Reference: RFC 8620, Section 3.6.1 4636 + Description: The request parsed as JSON but did not match the type 4637 + signature of the Request object. 4638 + 4639 + o JMAP Error Code: overQuota 4640 + Intended Use: Common 4641 + Change Controller: IETF 4642 + Reference: RFC 8620, Section 5.3 4643 + Description: The create would exceed a server-defined limit on the 4644 + number or total size of objects of this type. 4645 + 4646 + 4647 + 4648 + 4649 + 4650 + Jenkins & Newman Standards Track [Page 83] 4651 + 4652 + RFC 8620 JMAP July 2019 4653 + 4654 + 4655 + o JMAP Error Code: rateLimit 4656 + Intended Use: Common 4657 + Change Controller: IETF 4658 + Reference: RFC 8620, Section 5.3 4659 + Description: Too many objects of this type have been created 4660 + recently, and a server-defined rate limit has been reached. It 4661 + may work if tried again later. 4662 + 4663 + o JMAP Error Code: requestTooLarge 4664 + Intended Use: Common 4665 + Change Controller: IETF 4666 + Reference: RFC 8620, Sections 5.1 and 5.3 4667 + Description: The total number of actions exceeds the maximum 4668 + number the server is willing to process in a single method call. 4669 + 4670 + o JMAP Error Code: invalidResultReference 4671 + Intended Use: Common 4672 + Change Controller: IETF 4673 + Reference: RFC 8620, Section 3.6.2 4674 + Description: The method used a result reference for one of its 4675 + arguments, but this failed to resolve. 4676 + 4677 + o JMAP Error Code: serverFail 4678 + Intended Use: Common 4679 + Change Controller: IETF 4680 + Reference: RFC 8620, Section 3.6.2 4681 + Description: An unexpected or unknown error occurred during the 4682 + processing of the call. The method call made no changes to the 4683 + server's state. 4684 + 4685 + o JMAP Error Code: serverPartialFail 4686 + Intended Use: Limited 4687 + Change Controller: IETF 4688 + Reference: RFC 8620, Section 3.6.2 4689 + Description: Some, but not all, expected changes described by the 4690 + method occurred. The client MUST resynchronise impacted data to 4691 + determine the server state. Use of this error is strongly 4692 + discouraged. 4693 + 4694 + o JMAP Error Code: serverUnavailable 4695 + Intended Use: Common 4696 + Change Controller: IETF 4697 + Reference: RFC 8620, Section 3.6.2 4698 + Description: Some internal server resource was temporarily 4699 + unavailable. Attempting the same operation later (perhaps after a 4700 + backoff with a random factor) may succeed. 4701 + 4702 + 4703 + 4704 + 4705 + 4706 + Jenkins & Newman Standards Track [Page 84] 4707 + 4708 + RFC 8620 JMAP July 2019 4709 + 4710 + 4711 + o JMAP Error Code: singleton 4712 + Intended Use: Common 4713 + Change Controller: IETF 4714 + Reference: RFC 8620, Section 5.3 4715 + Description: This is a singleton type, so you cannot create 4716 + another one or destroy the existing one. 4717 + 4718 + o JMAP Error Code: stateMismatch 4719 + Intended Use: Common 4720 + Change Controller: IETF 4721 + Reference: RFC 8620, Section 5.3 4722 + Description: An ifInState argument was supplied, and it does not 4723 + match the current state. 4724 + 4725 + o JMAP Error Code: tooLarge 4726 + Intended Use: Common 4727 + Change Controller: IETF 4728 + Reference: RFC 8620, Section 5.3 4729 + Description: The action would result in an object that exceeds a 4730 + server-defined limit for the maximum size of a single object of 4731 + this type. 4732 + 4733 + o JMAP Error Code: tooManyChanges 4734 + Intended Use: Common 4735 + Change Controller: IETF 4736 + Reference: RFC 8620, Section 5.6 4737 + Description: There are more changes than the client's maxChanges 4738 + argument. 4739 + 4740 + o JMAP Error Code: unknownCapability 4741 + Intended Use: Common 4742 + Change Controller: IETF 4743 + Reference: RFC 8620, Section 3.6.1 4744 + Description: The client included a capability in the "using" 4745 + property of the request that the server does not support. 4746 + 4747 + o JMAP Error Code: unknownMethod 4748 + Intended Use: Common 4749 + Change Controller: IETF 4750 + Reference: RFC 8620, Section 3.6.2 4751 + Description: The server does not recognise this method name. 4752 + 4753 + o JMAP Error Code: unsupportedFilter 4754 + Intended Use: Common 4755 + Change Controller: IETF 4756 + Reference: RFC 8620, Section 5.5 4757 + Description: The filter is syntactically valid, but the server 4758 + cannot process it. 4759 + 4760 + 4761 + 4762 + Jenkins & Newman Standards Track [Page 85] 4763 + 4764 + RFC 8620 JMAP July 2019 4765 + 4766 + 4767 + o JMAP Error Code: unsupportedSort 4768 + Intended Use: Common 4769 + Change Controller: IETF 4770 + Reference: RFC 8620, Section 5.5 4771 + Description: The sort is syntactically valid but includes a 4772 + property the server does not support sorting on or a collation 4773 + method it does not recognise. 4774 + 4775 + o JMAP Error Code: willDestroy 4776 + Intended Use: Common 4777 + Change Controller: IETF 4778 + Reference: RFC 8620, Section 5.3 4779 + Description: The client requested an object be both updated and 4780 + destroyed in the same /set request, and the server has decided to 4781 + therefore ignore the update. 4782 + 4783 + 10. References 4784 + 4785 + 10.1. Normative References 4786 + 4787 + [EventSource] 4788 + Hickson, I., "Server-Sent Events", World Wide Web 4789 + Consortium Recommendation REC-eventsource-20150203, 4790 + February 2015, <https://www.w3.org/TR/eventsource/>. 4791 + 4792 + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 4793 + Requirement Levels", BCP 14, RFC 2119, 4794 + DOI 10.17487/RFC2119, March 1997, 4795 + <https://www.rfc-editor.org/info/rfc2119>. 4796 + 4797 + [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for 4798 + specifying the location of services (DNS SRV)", RFC 2782, 4799 + DOI 10.17487/RFC2782, February 2000, 4800 + <https://www.rfc-editor.org/info/rfc2782>. 4801 + 4802 + [RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, 4803 + DOI 10.17487/RFC2818, May 2000, 4804 + <https://www.rfc-editor.org/info/rfc2818>. 4805 + 4806 + [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: 4807 + Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, 4808 + <https://www.rfc-editor.org/info/rfc3339>. 4809 + 4810 + [RFC3553] Mealling, M., Masinter, L., Hardie, T., and G. Klyne, "An 4811 + IETF URN Sub-namespace for Registered Protocol 4812 + Parameters", BCP 73, RFC 3553, DOI 10.17487/RFC3553, June 4813 + 2003, <https://www.rfc-editor.org/info/rfc3553>. 4814 + 4815 + 4816 + 4817 + 4818 + Jenkins & Newman Standards Track [Page 86] 4819 + 4820 + RFC 8620 JMAP July 2019 4821 + 4822 + 4823 + [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 4824 + 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 4825 + 2003, <https://www.rfc-editor.org/info/rfc3629>. 4826 + 4827 + [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data 4828 + Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, 4829 + <https://www.rfc-editor.org/info/rfc4648>. 4830 + 4831 + [RFC4790] Newman, C., Duerst, M., and A. Gulbrandsen, "Internet 4832 + Application Protocol Collation Registry", RFC 4790, 4833 + DOI 10.17487/RFC4790, March 2007, 4834 + <https://www.rfc-editor.org/info/rfc4790>. 4835 + 4836 + [RFC5051] Crispin, M., "i;unicode-casemap - Simple Unicode Collation 4837 + Algorithm", RFC 5051, DOI 10.17487/RFC5051, October 2007, 4838 + <https://www.rfc-editor.org/info/rfc5051>. 4839 + 4840 + [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security 4841 + (TLS) Protocol Version 1.2", RFC 5246, 4842 + DOI 10.17487/RFC5246, August 2008, 4843 + <https://www.rfc-editor.org/info/rfc5246>. 4844 + 4845 + [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., 4846 + Housley, R., and W. Polk, "Internet X.509 Public Key 4847 + Infrastructure Certificate and Certificate Revocation List 4848 + (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008, 4849 + <https://www.rfc-editor.org/info/rfc5280>. 4850 + 4851 + [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, 4852 + DOI 10.17487/RFC5322, October 2008, 4853 + <https://www.rfc-editor.org/info/rfc5322>. 4854 + 4855 + [RFC6186] Daboo, C., "Use of SRV Records for Locating Email 4856 + Submission/Access Services", RFC 6186, 4857 + DOI 10.17487/RFC6186, March 2011, 4858 + <https://www.rfc-editor.org/info/rfc6186>. 4859 + 4860 + [RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S. 4861 + Cheshire, "Internet Assigned Numbers Authority (IANA) 4862 + Procedures for the Management of the Service Name and 4863 + Transport Protocol Port Number Registry", BCP 165, 4864 + RFC 6335, DOI 10.17487/RFC6335, August 2011, 4865 + <https://www.rfc-editor.org/info/rfc6335>. 4866 + 4867 + [RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M., 4868 + and D. Orchard, "URI Template", RFC 6570, 4869 + DOI 10.17487/RFC6570, March 2012, 4870 + <https://www.rfc-editor.org/info/rfc6570>. 4871 + 4872 + 4873 + 4874 + Jenkins & Newman Standards Track [Page 87] 4875 + 4876 + RFC 8620 JMAP July 2019 4877 + 4878 + 4879 + [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", 4880 + RFC 6749, DOI 10.17487/RFC6749, October 2012, 4881 + <https://www.rfc-editor.org/info/rfc6749>. 4882 + 4883 + [RFC6764] Daboo, C., "Locating Services for Calendaring Extensions 4884 + to WebDAV (CalDAV) and vCard Extensions to WebDAV 4885 + (CardDAV)", RFC 6764, DOI 10.17487/RFC6764, February 2013, 4886 + <https://www.rfc-editor.org/info/rfc6764>. 4887 + 4888 + [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type 4889 + Specifications and Registration Procedures", BCP 13, 4890 + RFC 6838, DOI 10.17487/RFC6838, January 2013, 4891 + <https://www.rfc-editor.org/info/rfc6838>. 4892 + 4893 + [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed., 4894 + "JavaScript Object Notation (JSON) Pointer", RFC 6901, 4895 + DOI 10.17487/RFC6901, April 2013, 4896 + <https://www.rfc-editor.org/info/rfc6901>. 4897 + 4898 + [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 4899 + Protocol (HTTP/1.1): Message Syntax and Routing", 4900 + RFC 7230, DOI 10.17487/RFC7230, June 2014, 4901 + <https://www.rfc-editor.org/info/rfc7230>. 4902 + 4903 + [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 4904 + Protocol (HTTP/1.1): Semantics and Content", RFC 7231, 4905 + DOI 10.17487/RFC7231, June 2014, 4906 + <https://www.rfc-editor.org/info/rfc7231>. 4907 + 4908 + [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, 4909 + DOI 10.17487/RFC7493, March 2015, 4910 + <https://www.rfc-editor.org/info/rfc7493>. 4911 + 4912 + [RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre, 4913 + "Recommendations for Secure Use of Transport Layer 4914 + Security (TLS) and Datagram Transport Layer Security 4915 + (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May 4916 + 2015, <https://www.rfc-editor.org/info/rfc7525>. 4917 + 4918 + [RFC7617] Reschke, J., "The 'Basic' HTTP Authentication Scheme", 4919 + RFC 7617, DOI 10.17487/RFC7617, September 2015, 4920 + <https://www.rfc-editor.org/info/rfc7617>. 4921 + 4922 + [RFC7807] Nottingham, M. and E. Wilde, "Problem Details for HTTP 4923 + APIs", RFC 7807, DOI 10.17487/RFC7807, March 2016, 4924 + <https://www.rfc-editor.org/info/rfc7807>. 4925 + 4926 + 4927 + 4928 + 4929 + 4930 + Jenkins & Newman Standards Track [Page 88] 4931 + 4932 + RFC 8620 JMAP July 2019 4933 + 4934 + 4935 + [RFC8030] Thomson, M., Damaggio, E., and B. Raymor, Ed., "Generic 4936 + Event Delivery Using HTTP Push", RFC 8030, 4937 + DOI 10.17487/RFC8030, December 2016, 4938 + <https://www.rfc-editor.org/info/rfc8030>. 4939 + 4940 + [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for 4941 + Writing an IANA Considerations Section in RFCs", BCP 26, 4942 + RFC 8126, DOI 10.17487/RFC8126, June 2017, 4943 + <https://www.rfc-editor.org/info/rfc8126>. 4944 + 4945 + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 4946 + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 4947 + May 2017, <https://www.rfc-editor.org/info/rfc8174>. 4948 + 4949 + [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 4950 + Interchange Format", STD 90, RFC 8259, 4951 + DOI 10.17487/RFC8259, December 2017, 4952 + <https://www.rfc-editor.org/info/rfc8259>. 4953 + 4954 + [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework: 4955 + Preparation, Enforcement, and Comparison of 4956 + Internationalized Strings in Application Protocols", 4957 + RFC 8264, DOI 10.17487/RFC8264, October 2017, 4958 + <https://www.rfc-editor.org/info/rfc8264>. 4959 + 4960 + [RFC8291] Thomson, M., "Message Encryption for Web Push", RFC 8291, 4961 + DOI 10.17487/RFC8291, November 2017, 4962 + <https://www.rfc-editor.org/info/rfc8291>. 4963 + 4964 + [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol 4965 + Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, 4966 + <https://www.rfc-editor.org/info/rfc8446>. 4967 + 4968 + [RFC8615] Nottingham, M., "Well-Known Uniform Resource Identifiers 4969 + (URIs)", RFC 8615, DOI 10.17487/RFC8615, May 2019, 4970 + <https://www.rfc-editor.org/info/rfc8615>. 4971 + 4972 + 10.2. Informative References 4973 + 4974 + [RFC8246] McManus, P., "HTTP Immutable Responses", RFC 8246, 4975 + DOI 10.17487/RFC8246, September 2017, 4976 + <https://www.rfc-editor.org/info/rfc8246>. 4977 + 4978 + 4979 + 4980 + 4981 + 4982 + 4983 + 4984 + 4985 + 4986 + Jenkins & Newman Standards Track [Page 89] 4987 + 4988 + RFC 8620 JMAP July 2019 4989 + 4990 + 4991 + Authors' Addresses 4992 + 4993 + Neil Jenkins 4994 + Fastmail 4995 + PO Box 234, Collins St. West 4996 + Melbourne, VIC 8007 4997 + Australia 4998 + 4999 + Email: neilj@fastmailteam.com 5000 + URI: https://www.fastmail.com 5001 + 5002 + 5003 + Chris Newman 5004 + Oracle 5005 + 440 E. Huntington Dr., Suite 400 5006 + Arcadia, CA 91006 5007 + United States of America 5008 + 5009 + Email: chris.newman@oracle.com 5010 + 5011 + 5012 + 5013 + 5014 + 5015 + 5016 + 5017 + 5018 + 5019 + 5020 + 5021 + 5022 + 5023 + 5024 + 5025 + 5026 + 5027 + 5028 + 5029 + 5030 + 5031 + 5032 + 5033 + 5034 + 5035 + 5036 + 5037 + 5038 + 5039 + 5040 + 5041 + 5042 + Jenkins & Newman Standards Track [Page 90] 5043 +