RFC 9425
JSON Meta Application Protocol (JMAP) for Quotas
1. Introduction ๐
Okay bestie, let's get into it! โจ This is RFC 9425: JSON Meta Application Protocol (JMAP) for Quotas ๐. It's a Standards Track doc from the IETF, written by R. Cordier, Ed. at Linagora Vietnam, dated June 2023 ๐ฆ. The ISSN is 2070-1721. The title block doesn't list anything it obsoletes or updates, so this one is standing on its own ๐ .
The whole thing is about one job: giving quota data a clean data model over JMAP, so a client can see the limit on an account and how much of it has been used ๐. The abstract says it plainly: this document "specifies a data model for handling quotas on accounts with a server using the JSON Meta Application Protocol (JMAP)" ๐ธ.
This is an Internet Standards Track document, and it reflects the IETF community's consensus after public review and approval by the IESG ๐ซถ. If you want more on Internet Standards, check Section 2 of RFC 7841. Errata and feedback live at https://www.rfc-editor.org/info/rfc9425.
Copyright is held by the IETF Trust and the document authors, 2023 ๐. The doc is subject to BCP 78 and the IETF Trust's Legal Provisions at https://trustee.ietf.org/license-info, so read those before you do anything with it, because they spell out your rights. Code Components pulled out of this doc must include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, per the Revised BSD License ๐.
1. Introduction
1.1. Notational Conventions
1.2. Terminology
2. Addition to the Capabilities Object
2.1. urn:ietf:params:jmap:quota
3. Sub-types of the Quota Data Type
3.1. Scope
3.2. ResourceType
4. Quota
4.1. Properties of the Quota Object
4.2. Quota/get
4.3. Quota/changes
4.4. Quota/query
4.5. Quota/queryChanges
5. Examples
5.1. Fetching Quotas
5.2. Requesting Latest Quota Changes
6. Push
7. IANA Considerations
7.1. JMAP Capability Registration for "quota"
7.2. JMAP Data Type Registration for "Quota"
8. Security Considerations
9. Normative References
Acknowledgements
Author's Address
JMAP [RFC8620] is a generic protocol for syncing data like mails, calendars, or contacts between a client and a server ๐ฌ. It's built for mobile and web environments and gives you one consistent interface across different data types โจ.
This spec defines a data model for quotas over JMAP, so a user can get the details about a given quota ๐ฆ. It does not cover quota administration, which should be handled by other means ๐ โโ๏ธ.
1.1. Notational Conventions
Okay, the key words here are a big deal ๐ฅ. "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be read as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in all capitals, exactly like this ๐ . Lowercase ones are just regular words, no cap ๐.
Type signatures, examples, and property descriptions follow the conventions in Section 1.1 of [RFC8620] ๐ธ. The data types defined in the core spec get used here too ๐.
1.2. Terminology
This doc reuses the terminology from the core JMAP spec, Section 1.6 of [RFC8620] ๐ง.
The term "Quota" (capitalized) refers to the data type defined in Section 4, and also to an instance of that data type ๐.
2. Addition to the Capabilities Object ๐
The capabilities object comes back as part of the JMAP Session object. See [RFC8620], Section 2 for that ๐ฆ.
This document defines one additional capability URI ๐.
2.1. urn:ietf:params:jmap:quota
This one represents support for the Quota data type and its associated API methods โจ. Servers supporting this spec MUST add a property called urn:ietf:params:jmap:quota to the capabilities object ๐ซถ. No skipping this one, bestie ๐ญ.
The value of that property is an empty object. It shows up in both the JMAP Session capabilities property and an account's accountCapabilities property ๐.
3. Sub-types of the Quota Data Type ๐ง
There are two fields inside the Quota data type that have an enumerated set of possible values. They are:
3.1. Scope
The Scope data type is how we represent the entities a quota applies to ๐ธ. It's defined as a String with values from this set:
account: The quota information applies to just the client's account ๐ .domain: The quota information applies to all accounts sharing this domain ๐ก.global: The quota information applies to all accounts belonging to the server ๐.
3.2. ResourceType
The ResourceType data type is the unit of measure for quota usage ๐. It's defined as a String with values from this set:
count: The quota is measured in a number of data type objects. For example, a quota can have a limit of 50 "Mail" objects ๐จ.octets: The quota is measured in size, in octets. For example, a quota can have a limit of 25000 octets ๐พ.
4. Quota ๐
The Quota is an object that shows the limit set on an account's usage. It also shows the current usage measured against that limit ๐. Iconic.
4.1. Properties of the Quota Object
The Quota object MUST contain the following fields ๐:
id:IdThe unique identifier for this object ๐.resourceType:StringThe resource type of the quota, as defined in Section 3.2 ๐.used:UnsignedIntThe current usage of the defined quota, measured in the "resourceType" unit. The server handles the computation of this value ๐งฎ.hardLimit:UnsignedIntThe hard limit set by this quota, measured in the "resourceType" unit. Objects in scope may not be created or updated once this limit is reached ๐ซ. Hard limit = hard stop, bestie ๐.scope:StringThe "Scope" of this quota, as defined in Section 3.1 ๐.name:StringThe name of the quota. It's useful for managing quotas and for searching with queries ๐.types:String[]A list of all the type names from the "JMAP Types Names" registry (like Email, Calendar, and so on) that this quota applies to. This lets quotas be assigned to distinct or shared data types ๐งฉ.
The server MUST filter out any types the client didn't request the associated capability for in the "using" section of the request ๐. The server MUST NOT return Quota objects that have no types recognized by the client ๐ โโ๏ธ. Non-negotiable, periodt ๐ .
The Quota object MAY contain the following fields ๐ธ:
warnLimit:UnsignedInt|nullThe warn limit set by this quota, measured in the "resourceType" unit. It's there to send a warning to an entity that's about to hit the hard limit soon, but no action has been taken yet ๐จ. If it's set, it SHOULD be lower than the "softLimit" (if present and not null) and the "hardLimit" ๐.softLimit:UnsignedInt|nullThe soft limit set by this quota, measured in the "resourceType" unit. It can still allow some operations while refusing others ๐. What's allowed is up to the server. For example, it could block outgoing events of an entity (sending emails, creating calendar events, and so on) while still letting incoming events through (receiving emails, receiving calendar events, and so on) ๐ฌ. If it's set, it SHOULD be higher than the "warnLimit" (if present and not null) but lower than the "hardLimit" ๐.description:String|nullAn arbitrary, free, human-readable description of this quota ๐. It might explain where the different limits come from, and which entities and data types the quota applies to ๐๏ธ. The description MUST be encoded in UTF-8 [RFC3629], as described in [RFC8620], Section 1.5, and selected based on an Accept-Language header in the request (as defined in [RFC9110], Section 12.5.4), or on out-of-band information about the user's language or locale ๐๐.
The following JMAP methods are supported ๐ .
4.2. Quota/get
This is the standard "/get" method, described in [RFC8620], Section 5.1 ๐. The _id_'s argument may be "null" to fetch all quotas of the account at once. You'll see that demonstrated in Section 5.1 โจ.
4.3. Quota/changes
This is the standard "/changes" method, described in [RFC8620], Section 5.2. It has one extra argument in the response ๐งฉ:
updatedProperties:String[]|nullIf only the "used" Quota property has changed since the old state, this will be a list containing only that property ๐. If the server can't tell whether only "used" has changed, it MUST be null ๐ซฃ.
"Used" changes all the time, but the other properties usually change only rarely ๐ธ. So the server can help the client optimize data transfer by tracking quota usage changes separately from other state changes ๐. The updatedProperties array can be used directly through a back-reference in a later Quota/get call in the same request. That way, only these properties come back when nothing else has changed ๐ฆ.
Servers MAY decide to add other properties to the list that they judge to be changing frequently ๐ซ.
You can see this method in action in Section 5.2 ๐.
4.4. Quota/query
This is a standard "/query" method, described in [RFC8620], Section 5.5 ๐.
A FilterCondition object has the following properties. Any of them may be included or left out ๐:
name:StringThe Quota _name_ property contains the given string ๐ท๏ธ.scope:StringThe Quota _scope_ property must match the given value exactly ๐ฏ.resourceType:StringThe Quota _resourceType_ property must match the given value exactly ๐.type:StringThe Quota _types_ property contains the given value ๐งฉ.
A Quota object matches the FilterCondition if, and only if, all the given conditions match. If zero properties are specified, it's automatically true for all objects ๐.
The following Quota properties MUST be supported for sorting ๐ฅ:
nameused
4.5. Quota/queryChanges
This is a standard "/queryChanges" method, described in [RFC8620], Section 5.6 โจ.
5.2. Requesting Latest Quota Changes โจ
Okay bestie, here's how you ask for just the quota changes since your last check ๐
Send a Quota/changes call with the sinceState you already have, then chain a Quota/get onto it using the back-references so you only fetch the quotas that actually changed ๐ฆ
Request fetching the changes for a specific quota:
[[ "Quota/changes", {
"accountId": "u33084183",
"sinceState": "78540",
"maxChanges": 20
}, "0" ],
[ "Quota/get", {
"accountId": "u33084183",
"#ids": {
"resultOf": "0",
"name": "Quota/changes",
"path": "/updated"
},
"#properties": {
"resultOf": "0",
"name": "Quota/changes",
"path": "/updatedProperties"
}
}, "1" ]]
With response:
[[ "Quota/changes", {
"accountId": "u33084183",
"oldState": "78540",
"newState": "78542",
"hasMoreChanges": false,
"updatedProperties": ["used"],
"created": [],
"updated": ["2a06df0d-9865-4e74-a92f-74dcc814270e"],
"destroyed": []
}, "0" ],
[ "Quota/get", {
"accountId": "u33084183",
"state": "10826",
"list": [{
"id": "2a06df0d-9865-4e74-a92f-74dcc814270e",
"used": 1246
}],
"notFound": []
}, "1" ]]
6. Push ๐
Servers MUST support the JMAP push mechanisms, as specified in [RFC8620], Section 7, so clients can get notified whenever the state changes for the Quota type defined in this spec ๐ซถ
7. IANA Considerations ๐ธ
7.1. JMAP Capability Registration for "quota" ๐
IANA has registered the "quota" JMAP Capability like this:
- Capability Name:
urn:ietf:params:jmap:quota - Reference: RFC 9425
- Intended Use: common
- Change Controller: IETF
- Security and Privacy Considerations: RFC 9425, Section 8
7.2. JMAP Data Type Registration for "Quota" ๐ง
IANA has registered the "Quota" Data Type like this:
- Type Name: Quota
- Can Reference Blobs: No
- Can Use for State Change: Yes
- Capability:
urn:ietf:params:jmap:quota - Reference: RFC 9425
8. Security Considerations ๐
Okay, this section is serious, so read it carefully ๐ญ
All security considerations of JMAP [RFC8620] apply to this specification ๐
Implementors need to be really careful that the extension in this document doesn't break the site's security policy ๐ The resource usage of other users is probably confidential info, so it should not be divulged to people who aren't authorized to see it.
Here's the tricky part: any resource shared across users (like a quota with the "domain" or "global" scope) means one user who can use that resource can affect what's left for everyone else. For example, a user could spam themselves with events and make the shared resource hit its limit and become unusable for others. Implementors could mitigate that with some rate-limiting on the server ๐ก๏ธ
Also, showing domain and global quota counts to all users can cause privacy leakage of other sensitive data, or at least reveal that the sensitive data exists. For example, some users are part of a private list that belongs to the server, so they shouldn't know how many users are on it. But if you compare the quota count before and after sending a message to that list, you could work out how many people are subscribed, because the domain or global quota count goes up by that number. To limit these attacks, quotas with "domain" or "global" scope SHOULD only be visible to server administrators and not to general users ๐
9. 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,https://www.rfc-editor.org/info/rfc2119. - [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI
10.17487/RFC3629, November 2003,https://www.rfc-editor.org/info/rfc3629. - [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI
10.17487/RFC8174, May 2017,https://www.rfc-editor.org/info/rfc8174. - [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application Protocol (JMAP)", RFC 8620, DOI
10.17487/RFC8620, July 2019,https://www.rfc-editor.org/info/rfc8620. - [RFC9007] Ouazana, R., Ed., "Handling Message Disposition Notification with the JSON Meta Application Protocol (JMAP)", RFC 9007, DOI
10.17487/RFC9007, March 2021,https://www.rfc-editor.org/info/rfc9007. - [RFC9110] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI
10.17487/RFC9110, June 2022,https://www.rfc-editor.org/info/rfc9110.
Acknowledgements ๐
Huge thanks to Michael Bailly, who co-wrote the first draft of this doc before deciding to go do other things ๐
Thank you to Benoit Tellier for his constant help and support while writing this ๐
Thank you to Raphael Ouazana for sharing his experience on how to write an RFC after finishing his own document: [RFC9007] โจ
Thank you to Bron Gondwana, Neil Jenkins, Alexey Melnikov, Joris Baum, and the whole IETF JMAP working group, who had extensive discussions and gave reviews and feedback ๐ฆ
Thank you to everyone in the IETF organization who took the time to read, understand, comment, and give great feedback in the last rounds ๐ซถ
Author's Address ๐๏ธ
Renรฉ Cordier (editor)
Linagora Vietnam
5 Dien Bien Phu
Hanoi
10000
Vietnam
Email: rcordier@linagora.com
URI: https://linagora.vn
๐ฆ where this page comes from
- ietf: rfc9425 2023-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms