From 4bfd864f10b68b71482b35c818559068ef8d5797 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Wed, 27 Nov 2024 20:54:24 +0100 Subject: doc: Add RFC documents --- doc/rfc/rfc9670.txt | 857 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 857 insertions(+) create mode 100644 doc/rfc/rfc9670.txt (limited to 'doc/rfc/rfc9670.txt') diff --git a/doc/rfc/rfc9670.txt b/doc/rfc/rfc9670.txt new file mode 100644 index 0000000..13dd689 --- /dev/null +++ b/doc/rfc/rfc9670.txt @@ -0,0 +1,857 @@ + + + + +Internet Engineering Task Force (IETF) N. Jenkins, Ed. +Request for Comments: 9670 Fastmail +Updates: 8620 November 2024 +Category: Standards Track +ISSN: 2070-1721 + + + JSON Meta Application Protocol (JMAP) Sharing + +Abstract + + This document specifies a data model for sharing data between users + using the JSON Meta Application Protocol (JMAP). Future documents + can reference this document when defining data types to support a + consistent model of sharing. + +Status of This Memo + + This is an Internet Standards Track document. + + This document is a product of the Internet Engineering Task Force + (IETF). It represents the consensus of the IETF community. It has + received public review and has been approved for publication by the + Internet Engineering Steering Group (IESG). Further information on + Internet Standards is available in Section 2 of RFC 7841. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + https://www.rfc-editor.org/info/rfc9670. + +Copyright Notice + + Copyright (c) 2024 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Revised BSD License text as described in Section 4.e of the + Trust Legal Provisions and are provided without warranty as described + in the Revised BSD License. + +Table of Contents + + 1. Introduction + 1.1. Notational Conventions + 1.2. Terminology + 1.3. Data Model Overview + 1.4. Subscribing to Shared Data + 1.5. Addition to the Capabilities Object + 1.5.1. urn:ietf:params:jmap:principals + 1.5.2. urn:ietf:params:jmap:principals:owner + 2. Principals + 2.1. Principal/get + 2.2. Principal/changes + 2.3. Principal/set + 2.4. Principal/query + 2.4.1. Filtering + 2.5. Principal/queryChanges + 3. ShareNotifications + 3.1. ShareNotification/get + 3.2. ShareNotification/changes + 3.3. ShareNotification/set + 3.4. ShareNotification/query + 3.4.1. Filtering + 3.4.2. Sorting + 3.5. ShareNotification/queryChanges + 4. Framework for Shared Data + 4.1. Example + 5. Internationalization Considerations + 6. Security Considerations + 6.1. Spoofing + 6.2. Unnoticed Sharing + 6.3. Denial of Service + 6.4. Unauthorized Principals + 7. IANA Considerations + 7.1. JMAP Capability Registration for "principals" + 7.2. JMAP Capability Registration for "principals:owner" + 7.3. JMAP Data Type Registration for "Principal" + 7.4. JMAP Data Type Registration for "ShareNotification" + 8. References + 8.1. Normative References + 8.2. Informative References + Author's Address + +1. Introduction + + The JSON Meta Application Protocol (JMAP) [RFC8620] is a generic + protocol for synchronizing data, such as mail, calendars, or + contacts, between a client and a server. It is optimized for mobile + and web environments and provides a consistent interface to query, + read, and modify different data types, including comprehensive error + handling. + + This specification defines a data model to represent entities in a + collaborative environment and a framework for sharing data between + them that can be used to provide a consistent sharing model for + different data types. It does not define _what_ may be shared or the + granularity of permissions, as this will depend on the data in + question. + +1.1. Notational Conventions + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as described in + BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all + capitals, as shown here. + + Type signatures, examples, and property descriptions in this document + follow the conventions established in Section 1.1 of [RFC8620]. Data + types defined in the core specification are also used in this + document. + + Examples of API exchanges only show the methodCalls array of the + Request object or the methodResponses array of the Response object. + For compactness, the rest of the Request/Response object is omitted. + +1.2. Terminology + + The same terminology is used in this document as in the core JMAP + specification. See [RFC8620], Section 1.6. + + The terms "Principal" and "ShareNotification" (with this specific + capitalization) are used to refer to the data types defined in this + document and instances of those data types. + +1.3. Data Model Overview + + A Principal (see Section 2) represents an individual, team, or + resource (e.g., a room or projector). The object contains + information about the entity being represented, such as a name, + description, and time zone. It may also hold domain-specific + information. A Principal may be associated with zero or more + Accounts (see [RFC8620], Section 1.6.2) containing data belonging to + the Principal. Managing the set of Principals within a system is out + of scope for this specification, as it is highly domain specific. It + is likely to map directly from a directory service or other user + management system. + + Data types may allow users to share data with others by assigning + permissions to Principals. When a user's permissions are changed, a + ShareNotification object is created for them so a client can inform + the user of the changes. + +1.4. Subscribing to Shared Data + + Permissions determine whether a user _may_ access data but not + whether they _want_ to. Some shared data is of equal importance as + the user's own, while other data is just there should the user wish + to explicitly go find it. Clients will often want to differentiate + the two. For example, a company may share mailing list archives for + all departments with all employees, but a user may only generally be + interested in the few they belong to. They would have _permission_ + to access many mailboxes but can _subscribe_ to just the ones they + care about. The client would provide separate interfaces for reading + mail in subscribed mailboxes and browsing all mailboxes they have + permission to access in order to manage those that they are + subscribed to. + + The JMAP Session object (see [RFC8620], Section 2) is defined to + include an object in the "accounts" property for every Account that + the user has access to. Collaborative systems may share data between + a very large number of Principals, most of which the user does not + care about day to day. For servers implementing this specification, + the Session object MUST only include Accounts where either the user + is subscribed to at least one record (see [RFC8620], Section 1.6.3) + in the Account or the Account belongs to the user. StateChange + events ([RFC8620], Section 7.1) for changes to data SHOULD only be + sent for data the user has subscribed to and MUST NOT be sent for any + Account where the user is not subscribed to any records in the + Account, except where that Account belongs to the user. + + The server MAY reject the user's attempt to subscribe to some + resources even if they have permission to access them (e.g., a + calendar representing a location). + + A user can query the set of Principals they have access to with + "Principal/query" (see Section 2.4). The Principal object will + contain an Account object for all Accounts where the user has + permission to access data for that Principal, even if they are not + yet subscribed. + +1.5. Addition to the Capabilities Object + + The capabilities object is returned as part of the JMAP Session + object; see [RFC8620], Section 2. This document defines two + additional capability URIs. + +1.5.1. urn:ietf:params:jmap:principals + + The urn:ietf:params:jmap:principals capability represents support for + the Principal and ShareNotification data types and associated API + methods. + + The value of this property in the JMAP Session "capabilities" + property is an empty object. + + The value of this property in an Account's "accountCapabilities" + property is an object that MUST contain the following information on + server capabilities and permissions for that Account: + + *currentUserPrincipalId*: Id|null + The id of the Principal in this Account that corresponds to the + user fetching this object, if any. + +1.5.2. urn:ietf:params:jmap:principals:owner + + The URI urn:ietf:params:jmap:principals:owner is solely used as a key + in an Account's "accountCapabilities" property. It does not appear + in the JMAP Session capabilities -- support is indicated by the + urn:ietf:params:jmap:principals URI being present in the session + capabilities. + + If urn:ietf:params:jmap:principals:owner is a key in an Account's + "accountCapabilities" property, that Account (and the data therein) + is owned by a Principal. Some Accounts may not be owned by a + Principal (e.g., the Account that contains the data for the + Principals themselves), in which case this property is omitted. + + The value of this property is an object with the following + properties: + + *accountIdForPrincipal*: Id + The id of an Account with the urn:ietf:params:jmap:principals + capability that contains the corresponding Principal object. + + *principalId*:Id + The id of the Principal that owns this Account. + +2. Principals + + A Principal represents an individual, a group, a location (e.g., a + room), a resource (e.g., a projector), or another entity in a + collaborative environment. Sharing in JMAP is generally configured + by assigning rights to certain data within an Account to other + Principals. For example, a user may assign permission to read their + calendar to a Principal representing another user or their team. + + In a shared environment, such as a workplace, a user may have access + to a large number of Principals. + + In most systems, the user will have access to a single Account + containing Principal objects. In some situations, for example, when + aggregating data from different places, there may be multiple + Accounts containing Principal objects. + + A *Principal* object has the following properties: + + *id*: Id (immutable; server-set) + The id of the Principal. + + *type*: String + This MUST be one of the following values: + + * "individual": This represents a single person. + * "group": This represents a group of other Principals. + * "resource": This represents some resource, e.g., a projector. + * "location": This represents a location. + * "other": This represents some other undefined Principal. + + *name*: String + The name of the Principal, e.g., "Jane Doe" or "Room 4B". + + *description*: String|null + A longer description of the Principal, for example, details about + the facilities of a resource, or null if no description is + available. + + *email*: String|null + An email address for the Principal, or null if no email is + available. If given, the value MUST conform to the "addr-spec" + syntax, as defined in [RFC5322], Section 3.4.1. + + *timeZone*: String|null + The time zone for this Principal, if known. If not null, the + value MUST be a time zone name from the IANA Time Zone Database + [IANA-TZDB]. + + *capabilities*: String[Object] (server-set) + A map of JMAP capability URIs to domain-specific information about + the Principal in relation to that capability, as defined in the + document that registered the capability. + + *accounts*: Id[Account]|null (server-set) + A map of Account id to Account object for each JMAP Account + containing data for this Principal that the user has access to, or + null if none. + +2.1. Principal/get + + This is a standard "/get" method as described in [RFC8620], + Section 5.1. + +2.2. Principal/changes + + This is a standard "/changes" method as described in [RFC8620], + Section 5.2. + + | Note: Implementations backed by an external directory may be + | unable to calculate changes. In this case, they will always + | return a "cannotCalculateChanges" error as described in the + | core JMAP specification. + +2.3. Principal/set + + This is a standard "/set" method as described in [RFC8620], + Section 5.3. + + Managing Principals is likely tied to a directory service or some + other vendor-specific solution. This management may occur out of + band or via an additional capability defined elsewhere. Allowing + direct user modification of properties has security considerations, + as noted in Section 6. A server MUST reject any change it doesn't + allow with a "forbidden" SetError. + + Where a server does support changes via this API, it SHOULD allow an + update to the "name", "description", and "timeZone" properties of the + Principal with the same id as the "currentUserPrincipalId" in the + Account capabilities. This allows the user to update their own + details. + +2.4. Principal/query + + This is a standard "/query" method as described in [RFC8620], + Section 5.5. + +2.4.1. Filtering + + A *FilterCondition* object has the following properties, all of which + are optional: + + *accountIds*: String[] + A list of Account ids. The Principal matches if any of the ids in + this list are keys in the Principal's "accounts" property (i.e., + if any of the Account ids belong to the Principal). + + *email*: String + The email property of the Principal contains the given string. + + *name*: String + The name property of the Principal contains the given string. + + *text*: String + The name, email, or description property of the Principal contains + the given string. + + *type*: String + The type must be exactly as given to match the condition. + + *timeZone*: String + The timeZone must be exactly as given to match the condition. + + All given conditions in the FilterCondition object must match for the + Principal to match. + + Text matches for "contains" SHOULD be simple substring matches. + +2.5. Principal/queryChanges + + This is a standard "/queryChanges" method as described in [RFC8620], + Section 5.6. + + | Note: Implementations backed by an external directory may be + | unable to calculate changes. In this case, they will always + | return a "cannotCalculateChanges" error as described in the + | core JMAP specification. + +3. ShareNotifications + + The ShareNotification data type records when the user's permissions + to access a shared object changes. ShareNotifications are only + created by the server; users cannot create them explicitly. They are + stored in the same Account as the Principals. + + Clients may present the list of notifications to the user and allow + the user to dismiss them. To dismiss a notification, use a standard + "/set" call to destroy it. + + The server SHOULD create a ShareNotification whenever the user's + permissions change on an object. It MAY choose not to create a + notification for permission changes to a group Principal, even if the + user is in the group, if this is more likely to be overwhelming than + helpful, or if it would create excessive notifications within the + system. + + The server MAY limit the maximum number of notifications it will + store for a user. When the limit is reached, any new notification + will cause the previously oldest notification to be automatically + deleted. + + The server MAY coalesce notifications if appropriate or remove + notifications after a certain period of time or that it deems are no + longer relevant. + + A *ShareNotification* object has the following properties: + + *id*: String (immutable; server-set) + The id of the ShareNotification. + + *created*: UTCDate (immutable; server-set) + The time this notification was created. + + *changedBy*: Entity (immutable; server-set) + Who made the change. An *Entity* object has the following + properties: + + *name*: String + The name of the entity who made the change. + *email*: String|null + The email of the entity who made the change, or null if no + email is available. + *principalId*: Id|null + The id of the Principal corresponding to the entity who made + the change, or null if no associated Principal. + + *objectType*: String (immutable; server-set) + The name of the data type for the object whose permissions have + changed, as registered in the IANA "JMAP Data Types" registry + [IANA-JMAP], e.g., "Calendar" or "Mailbox". + + *objectAccountId*: Id (immutable; server-set) + The id of the Account where this object exists. + + *objectId*: Id (immutable; server-set) + The id of the object that this notification is about. + + *oldRights*: String[Boolean]|null (immutable; server-set) + The "myRights" property of the object for the user before the + change. + + *newRights*: String[Boolean]|null (immutable; server-set) + The "myRights" property of the object for the user after the + change. + + *name*: String (immutable; server-set) + The name of the object at the time the notification was made. + Determining the name will depend on the data type in question. + For example, it might be the "title" property of a CalendarEvent + or the "name" of a Mailbox. The name is to show users who have + had their access rights to the object removed what it is that they + can no longer access. + +3.1. ShareNotification/get + + This is a standard "/get" method as described in [RFC8620], + Section 5.1. + +3.2. ShareNotification/changes + + This is a standard "/changes" method as described in [RFC8620], + Section 5.2. + +3.3. ShareNotification/set + + This is a standard "/set" method as described in [RFC8620], + Section 5.3. + + Only destroy is supported; any attempt to create/update MUST be + rejected with a "forbidden" SetError. + +3.4. ShareNotification/query + + This is a standard "/query" method as described in [RFC8620], + Section 5.5. + +3.4.1. Filtering + + A *FilterCondition* object has the following properties, all of which + are optional: + + *after*: UTCDate|null + The creation date must be on or after this date to match the + condition. + + *before*: UTCDate|null + The creation date must be before this date to match the condition. + + *objectType*: String + The objectType value must be identical to the given value to match + the condition. + + *objectAccountId*: Id + The objectAccountId value must be identical to the given value to + match the condition. + + All given conditions in the FilterCondition object must match for the + ShareNotification to match. + +3.4.2. Sorting + + The "created" property MUST be supported for sorting. + +3.5. ShareNotification/queryChanges + + This is a standard "/queryChanges" method as described in [RFC8620], + Section 5.6. + +4. Framework for Shared Data + + Shareable data types MUST define the following three properties: + + *isSubscribed*: Boolean + The value true indicates that the user wishes to subscribe to see + this data. The value false indicates that the user does not wish + to subscribe to see this data. The initial value for this + property when data is shared by another user is implementation + dependent, although data types may give advice on appropriate + defaults. + + *myRights*: String[Boolean] + The set of permissions the user currently has. Appropriate + permissions are domain specific and must be defined per data type. + Each key is the name of a permission defined for that data type. + The value for the key is true if the user has the permission or + false if they do not. + + *shareWith*: Id[String[Boolean]]|null + The value of this property is null if the data is not shared with + anyone. Otherwise, it is a map where each key is the id of a + Principal with which this data is shared, and the value associated + with that key is the rights to give that Principal, in the same + format as the "myRights" property. The Account id for the + Principal id can be found in the capabilities of the Account this + object is in (see Section 1.5.2). + + Users with appropriate permission may set this property to modify + who the data is shared with. The Principal that owns the Account + that this data is in MUST NOT be in the map, since the owner's + rights are implicit. + +4.1. Example + + Suppose we are designing a data model for a very simple to-do list. + There is a Todo data type representing a single item to do, each of + which belongs to a single TodoList. The specification makes the + TodoLists shareable by referencing this document and defining the + common properties. + + First, it would define a set of domain-specific rights. For example, + a TodoListRights object may have the following properties: + + *mayRead*: Boolean + The user may fetch this TodoList and any Todos that belong to this + TodoList. + + *mayWrite*: Boolean + The user may create, update, or destroy Todos that belong to this + TodoList and may change the "name" property of this TodoList. + + *mayAdmin*: Boolean + The user may see and modify the "myRights" property of this + TodoList and may destroy this TodoList. + + Then in the TodoList data type, we would include the three common + properties described in Section 4, in addition to any type-specific + properties (like "name" in this case): + + *id*: Id (immutable; server-set) + The id of the object. + + *name*: String + A name for this list of Todos. + + *isSubscribed*: Boolean + True if the user has indicated they wish to see this list. If + false, clients should not display this TodoList with the user's + other TodoLists but should provide a means for users to see and + subscribe to all TodoLists that have been shared with them. + + *myRights*: TodoListRights + The set of permissions the user currently has for this TodoList. + + *shareWith*: Id[TodoListRights]|null + If not shared with anyone, the value is null. Otherwise, it's a + map where the keys are Principal ids and the values are the rights + given to those Principals. Users with the "mayAdmin" right may + set this property to modify who the data is shared with. The + Principal that owns the Account that this data is in MUST NOT be + in the map; their rights are implicit. + + We would also define a new Principal capability with two properties: + + *accountId*: Id|null + The accountId containing the Todo data for this Principal, if it + has been shared with the requesting user. + + *mayShareWith*: Boolean + The user may give this Principal permission to access a TodoList. + + A client wishing to let the user configure sharing would look at the + "capabilities" for the Account containing the user's Todo data and + find the "urn:ietf:params:jmap:principals:owner" property, as per + Section 1.5.2. For example, the JMAP Session object might contain: + + { + "accounts": { + "u12345678": { + "name": "jane.doe@example.com", + "isPersonal": true, + "isReadOnly": false, + "accountCapabilities": { + "urn:com.example:jmap:todo": {}, + "urn:ietf:params:jmap:principals:owner": { + "accountIdForPrincipal": "u33084183", + "principalId": "P105aga511jaa" + } + } + }, + ... + }, + ... + } + + Figure 1: Part of a JMAP Session Object + + From this, the client now knows which Account has the Principal data, + and it can fetch the list of Principals and offer to share it with + the user by making an API request like this: + + [[ "Principal/get", { + "accountId": "u33084183", + "ids": null + }, "0" ]] + + Figure 2: "methodCalls" Property of a JMAP Request + + Here's an example response (where "Joe Bloggs" is another user that + this user could share their TodoList with; Joe has not shared any of + their own data with this user, so the "accounts" property is null): + + [[ "Principal/get", { + "accountId": "u33084183", + "state": "7b8eff5zz", + "list": [{ + "id": "P2342fnddd20", + "type": "individual", + "name": "Joe Bloggs", + "description": null, + "email": "joe.bloggs@example.com", + "timeZone": "Australia/Melbourne", + "capabilities": { + "urn:com.example:jmap:todo": { + "accountId": null, + "mayShareWith": true + } + }, + "accounts": null + }, { + "id": "P674pp24095qo49pr", + "name": "Board room", + "type": "location", + ... + }, ... ], + "notFound": [] + }, "0" ]] + + Figure 3: "methodResponses" Property of a JMAP Response + + A TodoList can be shared with "Joe Bloggs" by updating its shareWith + property, as in this example request: + + [[ "TodoList/set", { + "accountId": "u12345678", + "update": { + "tl01n231": { + "shareWith": { + "P2342fnddd20": { + "mayRead": true, + "mayWrite": true, + "mayAdmin": false + } + } + } + } + }, "0" ]] + + Figure 4: "methodCalls" Property of a JMAP Request + +5. Internationalization Considerations + + Experience has shown that unrestricted use of Unicode can lead to + problems such as inconsistent rendering, users reading text and + interpreting it differently than intended, and unexpected results + when copying text from one location to another. Servers MAY choose + to mitigate this by restricting the set of characters allowed in + otherwise unconstrained String fields. The FreeformClass, as + documented in [RFC8264], Section 4.3, might be a good starting point + for this. + + Attempts to set a value containing code points outside of the + permissible set can be handled in a few ways by the server. The + first option is to simply strip the forbidden characters and store + the resulting string. This is likely to be appropriate for control + characters, for example, where they can end up in data accidentally + due to copy-and-paste issues and are probably invisible to the end + user. JMAP allows the server to transform data on create/update, as + long as any changed properties are returned to the client in the + "/set" response so it knows what has changed, as per [RFC8620], + Section 5.3. Alternatively, the server MAY just reject the create/ + update with an "invalidProperties" SetError. + +6. Security Considerations + + All security considerations of JMAP [RFC8620] apply to this + specification. Additional considerations are detailed below. + +6.1. Spoofing + + Allowing users to edit their own Principal's name (and, to a lesser + extent, email, description, or type) could allow a user to change + their Principal to look like another user in the system, potentially + tricking others into sharing private data with them. Servers may + choose to forbid this and SHOULD keep logs of such changes to provide + an audit trail. + + Note that simply forbidding the use of a name already in the system + is insufficient protection, as a malicious user could still change + their name to something easily confused with the existing name by + using trivial misspellings or visually similar Unicode characters. + +6.2. Unnoticed Sharing + + Sharing data with another user allows someone to turn a transitory + account compromise (e.g., brief access to an unlocked or logged-in + client) into a persistent compromise (by setting up sharing with a + user that is controlled by the attacker). This can be mitigated by + requiring further authorization for configuring sharing or sending + notifications to the sharer via another channel whenever a new + permission is added. + +6.3. Denial of Service + + By creating many changes to the sharing status of objects, a user can + cause many ShareNotifications to be generated, which could lead to + resource exhaustion. Servers can mitigate this by coalescing + multiple changes to the same object into a single notification, + limiting the maximum number of notifications it stores per user and/ + or rate-limiting the changes to sharing permissions in the first + place. Automatically deleting older notifications after reaching a + limit can mean the user is not made aware of a sharing change, which + can itself be a security issue. For this reason, it is better to + coalesce changes and use other mitigation strategies. + +6.4. Unauthorized Principals + + The set of Principals within a shared environment MUST be strictly + controlled. If adding a new Principal is open to the public, risks + include: + + * An increased risk of a user accidentally sharing data with an + unintended person. + * An attacker sharing unwanted or offensive information with the + user. + * An attacker sharing items with spam content in the names in order + to generate ShareNotification objects, which are likely to be + prominently displayed to the user receiving them. + +7. IANA Considerations + +7.1. JMAP Capability Registration for "principals" + + IANA has registered "principals" in the "JMAP Capabilities" registry + as follows: + + Capability Name: urn:ietf:params:jmap:principals + Intended Use: common + Change Controller: IETF + Security and Privacy Considerations: RFC 9670, Section 6 + Reference: RFC 9670 + +7.2. JMAP Capability Registration for "principals:owner" + + IANA has registered "principals:owner" in the "JMAP Capabilities" + registry as follows: + + Capability Name: urn:ietf:params:jmap:principals:owner + Intended Use: common + Change Controller: IETF + Security and Privacy Considerations: RFC 9670, Section 6 + Reference: RFC 9670 + +7.3. JMAP Data Type Registration for "Principal" + + IANA has registered "Principal" in the "JMAP Data Types" registry as + follows: + + Type Name: Principal + Can Reference Blobs: No + Can Use for State Change: Yes + Capability: urn:ietf:params:jmap:principals + Reference: RFC 9670 + +7.4. JMAP Data Type Registration for "ShareNotification" + + IANA has registered "ShareNotification" in the "JMAP Data Types" + registry as follows: + + Type Name: ShareNotification + Can Reference Blobs: No + Can Use for State Change: Yes + Capability: urn:ietf:params:jmap:principals + Reference: RFC 9670 + +8. References + +8.1. Normative References + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, + DOI 10.17487/RFC2119, March 1997, + . + + [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, + DOI 10.17487/RFC5322, October 2008, + . + + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, + May 2017, . + + [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application + Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July + 2019, . + +8.2. Informative References + + [IANA-JMAP] + IANA, "JMAP Data Types", + . + + [IANA-TZDB] + IANA, "Time Zone Database", + . + + [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework: + Preparation, Enforcement, and Comparison of + Internationalized Strings in Application Protocols", + RFC 8264, DOI 10.17487/RFC8264, October 2017, + . + +Author's Address + + Neil Jenkins (editor) + Fastmail + PO Box 234, Collins St West + Melbourne VIC 8007 + Australia + Email: neilj@fastmailteam.com + URI: https://www.fastmail.com -- cgit v1.2.3