aboutsummaryrefslogtreecommitdiff
path: root/draft-jchat-00.txt
diff options
context:
space:
mode:
Diffstat (limited to 'draft-jchat-00.txt')
-rw-r--r--draft-jchat-00.txt745
1 files changed, 745 insertions, 0 deletions
diff --git a/draft-jchat-00.txt b/draft-jchat-00.txt
new file mode 100644
index 0000000..d044940
--- /dev/null
+++ b/draft-jchat-00.txt
@@ -0,0 +1,745 @@
+Internet Engineering Task Force (IETF) C. Smith
+Internet-Draft Fastmail
+Intended status: Standards Track August 15, 2025
+Expires: February 16, 2026
+
+
+ The JSON Chat Application Protocol (JCHAT)
+ draft-jchat-00
+
+Abstract
+
+ This document specifies a protocol for real-time chat messaging
+ built on top of the JSON Meta Application Protocol (JMAP) [RFC8620].
+ JCHAT provides a standardized way to exchange chat messages,
+ manage conversations, handle user presence, and synchronize chat
+ state across multiple devices efficiently.
+
+Status of This Memo
+
+ This Internet-Draft is submitted in full conformance with the
+ provisions of BCP 78 and BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF). Note that other groups may also distribute
+ working documents as Internet-Drafts. The list of current Internet-
+ Drafts is at https://datatracker.ietf.org/drafts/current/.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ This Internet-Draft will expire on February 16, 2026.
+
+Copyright Notice
+
+ Copyright (c) 2025 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.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3
+ 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4
+ 2. JCHAT Capability . . . . . . . . . . . . . . . . . . . . . . 4
+ 3. Data Types . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 3.1. Conversation . . . . . . . . . . . . . . . . . . . . . . 5
+ 3.2. Message . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.3. Participant . . . . . . . . . . . . . . . . . . . . . . . 10
+ 3.4. Presence . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 4. Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
+ 4.1. Conversation Methods . . . . . . . . . . . . . . . . . . . 12
+ 4.1.1. Conversation/get . . . . . . . . . . . . . . . . . . . 12
+ 4.1.2. Conversation/set . . . . . . . . . . . . . . . . . . . 13
+ 4.1.3. Conversation/changes . . . . . . . . . . . . . . . . . 15
+ 4.1.4. Conversation/query . . . . . . . . . . . . . . . . . . 15
+ 4.2. Message Methods . . . . . . . . . . . . . . . . . . . . . 17
+ 4.2.1. Message/get . . . . . . . . . . . . . . . . . . . . . 17
+ 4.2.2. Message/set . . . . . . . . . . . . . . . . . . . . . 18
+ 4.2.3. Message/changes . . . . . . . . . . . . . . . . . . . 20
+ 4.2.4. Message/query . . . . . . . . . . . . . . . . . . . . 20
+ 4.3. Participant Methods . . . . . . . . . . . . . . . . . . . 22
+ 4.3.1. Participant/get . . . . . . . . . . . . . . . . . . . 22
+ 4.3.2. Participant/set . . . . . . . . . . . . . . . . . . . 23
+ 4.3.3. Participant/changes . . . . . . . . . . . . . . . . . 24
+ 4.4. Presence Methods . . . . . . . . . . . . . . . . . . . . . 25
+ 4.4.1. Presence/get . . . . . . . . . . . . . . . . . . . . . 25
+ 4.4.2. Presence/set . . . . . . . . . . . . . . . . . . . . . 26
+ 5. Push Notifications . . . . . . . . . . . . . . . . . . . . . 27
+ 6. Security Considerations . . . . . . . . . . . . . . . . . . . 28
+ 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 29
+ 8. References . . . . . . . . . . . . . . . . . . . . . . . . . 29
+ 8.1. Normative References . . . . . . . . . . . . . . . . . . . 29
+ 8.2. Informative References . . . . . . . . . . . . . . . . . . 30
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 30
+
+1. Introduction
+
+ Modern chat applications require real-time message delivery,
+ efficient synchronization across multiple devices, and robust
+ handling of conversations with multiple participants. The JSON
+ Meta Application Protocol (JMAP) [RFC8620] provides an excellent
+ foundation for building such applications with its efficient
+ delta synchronization, push notifications, and batched operations.
+
+ JCHAT builds upon JMAP to provide:
+
+ o Structured conversation management with metadata
+ o Real-time message delivery and synchronization
+ o Participant management and permissions
+ o User presence information
+ o Message threading and replies
+ o Rich message content including attachments
+ o Message delivery receipts and read status
+
+ This specification defines the data model and methods for a
+ chat system that can scale from simple one-on-one messaging
+ to large group conversations while maintaining the efficiency
+ benefits of JMAP.
+
+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.
+
+ The underlying format used for this specification is JSON.
+ Consequently, the terms "object" and "array" as well as the four
+ primitive types (strings, numbers, booleans, and null) are to be
+ interpreted as described in Section 1 of [RFC8259].
+
+ Type signatures follow the conventions established in [RFC8620].
+
+1.2. Terminology
+
+ Conversation: A container for messages between one or more
+ participants. Conversations have metadata such as a title,
+ creation time, and participant list.
+
+ Message: A single communication within a conversation, containing
+ text content, metadata, and optionally attachments or replies
+ to other messages.
+
+ Participant: A user who is a member of a conversation and can
+ send and receive messages within that conversation.
+
+ Presence: Information about a user's current availability status
+ and activity.
+
+2. JCHAT Capability
+
+ The JCHAT capability is identified by the URI:
+
+ "urn:ietf:params:jmap:chat"
+
+ This capability is advertised in the "capabilities" object of
+ the JMAP Session response. The value of this capability in the
+ capabilities object MUST be an object with the following properties:
+
+ o maxConversationsPerAccount: "UnsignedInt|null"
+ The maximum number of conversations allowed per account.
+ If null, there is no limit.
+
+ o maxParticipantsPerConversation: "UnsignedInt|null"
+ The maximum number of participants allowed in a single
+ conversation. If null, there is no limit.
+
+ o maxMessageLength: "UnsignedInt|null"
+ The maximum length in UTF-8 octets of a message body.
+ If null, there is no limit.
+
+ o supportedMessageTypes: "String[]"
+ A list of message content types supported by the server.
+ MUST include "text/plain". MAY include "text/html",
+ "text/markdown", and others.
+
+ o maxAttachmentSize: "UnsignedInt|null"
+ The maximum size in octets of a single attachment.
+ If null, attachments are not supported.
+
+3. Data Types
+
+3.1. Conversation
+
+ A *Conversation* object represents a chat conversation between
+ one or more participants. It has the following properties:
+
+ o id: "Id" (immutable; server-set)
+ The id of the conversation.
+
+ o title: "String|null"
+ A user-defined title for the conversation. If null, clients
+ SHOULD generate a title from participant names.
+
+ o description: "String|null"
+ An optional description of the conversation purpose.
+
+ o createdAt: "UTCDate" (immutable; server-set)
+ The date and time the conversation was created.
+
+ o updatedAt: "UTCDate" (server-set)
+ The date and time the conversation was last modified.
+
+ o isArchived: "Boolean" (default: false)
+ Whether this conversation has been archived by the user.
+
+ o isMuted: "Boolean" (default: false)
+ Whether notifications for this conversation are muted.
+
+ o participantIds: "Id[]"
+ The list of participant IDs who are members of this
+ conversation. The order MAY be significant for display purposes.
+
+ o lastMessageId: "Id|null" (server-set)
+ The ID of the most recent message in this conversation.
+ null if the conversation has no messages.
+
+ o lastMessageAt: "UTCDate|null" (server-set)
+ The timestamp of the most recent message in this conversation.
+ null if the conversation has no messages.
+
+ o unreadCount: "UnsignedInt" (server-set)
+ The number of unread messages in this conversation for
+ this user.
+
+ o messageCount: "UnsignedInt" (server-set)
+ The total number of messages in this conversation.
+
+ o metadata: "String[String]|null"
+ Application-specific metadata as key-value pairs.
+
+3.2. Message
+
+ A *Message* object represents a single message within a conversation.
+ It has the following properties:
+
+ o id: "Id" (immutable; server-set)
+ The id of the message.
+
+ o conversationId: "Id" (immutable)
+ The id of the conversation this message belongs to.
+
+ o senderId: "Id" (immutable)
+ The id of the participant who sent this message.
+
+ o sentAt: "UTCDate" (immutable; server-set)
+ The date and time the message was sent.
+
+ o receivedAt: "UTCDate" (immutable; server-set)
+ The date and time the message was received by the server.
+
+ o editedAt: "UTCDate|null" (server-set)
+ The date and time the message was last edited. null if
+ never edited.
+
+ o body: "String"
+ The main content of the message.
+
+ o bodyType: "String" (default: "text/plain")
+ The MIME type of the message body. Servers MUST support
+ "text/plain". MAY support "text/html", "text/markdown".
+
+ o attachments: "Attachment[]|null"
+ A list of file attachments associated with this message.
+ null if no attachments.
+
+ o replyToMessageId: "Id|null"
+ The id of the message this message is replying to.
+ null if not a reply.
+
+ o isSystemMessage: "Boolean" (immutable; default: false)
+ Whether this is a system-generated message (e.g., user
+ joined/left conversation).
+
+ o isDeleted: "Boolean" (default: false)
+ Whether this message has been marked as deleted.
+
+ o reactions: "Reaction[]|null" (server-set)
+ A list of emoji reactions to this message. null if no reactions.
+
+ o deliveryStatus: "DeliveryStatus" (server-set)
+ The delivery status of this message.
+
+ o readBy: "MessageRead[]" (server-set)
+ A list of participants who have read this message.
+
+ o metadata: "String[String]|null"
+ Application-specific metadata as key-value pairs.
+
+ An *Attachment* object has the following properties:
+
+ o blobId: "Id"
+ The blob id of the attachment data.
+
+ o name: "String"
+ The filename of the attachment.
+
+ o type: "String"
+ The MIME type of the attachment.
+
+ o size: "UnsignedInt"
+ The size of the attachment in octets.
+
+ A *Reaction* object has the following properties:
+
+ o emoji: "String"
+ The Unicode emoji character(s) for the reaction.
+
+ o participantIds: "Id[]"
+ The list of participant IDs who added this reaction.
+
+ A *DeliveryStatus* is a string with one of the following values:
+
+ o "sending": The message is being sent to the server.
+ o "sent": The message has been accepted by the server.
+ o "delivered": The message has been delivered to all online
+ participants.
+ o "failed": The message failed to send.
+
+ A *MessageRead* object has the following properties:
+
+ o participantId: "Id"
+ The id of the participant who read the message.
+
+ o readAt: "UTCDate"
+ When the participant read the message.
+
+3.3. Participant
+
+ A *Participant* object represents a user's membership in a
+ conversation. It has the following properties:
+
+ o id: "Id" (immutable; server-set)
+ The id of the participant record.
+
+ o conversationId: "Id" (immutable)
+ The id of the conversation.
+
+ o userId: "Id" (immutable)
+ The id of the user account.
+
+ o displayName: "String"
+ The display name for this participant in this conversation.
+
+ o avatarBlobId: "Id|null"
+ The blob id of the participant's avatar image. null if
+ no custom avatar.
+
+ o role: "String" (default: "member")
+ The participant's role in the conversation. Possible values:
+ "owner", "admin", "member", "observer".
+
+ o joinedAt: "UTCDate" (immutable; server-set)
+ When the participant joined the conversation.
+
+ o lastActiveAt: "UTCDate|null" (server-set)
+ When the participant was last active in this conversation.
+ null if never active.
+
+ o isActive: "Boolean" (server-set)
+ Whether the participant is currently an active member
+ of the conversation.
+
+ o permissions: "String[]"
+ The list of permissions this participant has in the
+ conversation. Possible values: "send", "edit", "delete",
+ "invite", "remove", "manage".
+
+ o metadata: "String[String]|null"
+ Application-specific metadata as key-value pairs.
+
+3.4. Presence
+
+ A *Presence* object represents a user's current availability
+ status. It has the following properties:
+
+ o userId: "Id" (immutable)
+ The id of the user account.
+
+ o status: "String"
+ The user's current status. Possible values: "online",
+ "away", "busy", "offline".
+
+ o statusMessage: "String|null"
+ An optional custom status message.
+
+ o lastSeenAt: "UTCDate|null" (server-set)
+ When the user was last seen online. null if currently online
+ or privacy settings prevent sharing.
+
+ o updatedAt: "UTCDate" (server-set)
+ When the presence information was last updated.
+
+4. Methods
+
+4.1. Conversation Methods
+
+4.1.1. Conversation/get
+
+ Standard "/get" method as described in [RFC8620], Section 5.1.
+
+ The following additional properties are supported in the response:
+
+ Additional errors:
+
+ None specific to this method.
+
+4.1.2. Conversation/set
+
+ Standard "/set" method as described in [RFC8620], Section 5.3.
+
+ When creating a new conversation, the following properties are
+ required in the create object:
+
+ o participantIds: Must include at least the creating user.
+
+ The following properties MUST NOT be included when creating
+ a conversation:
+
+ o id, createdAt, updatedAt, lastMessageId, lastMessageAt,
+ unreadCount, messageCount
+
+ When updating a conversation, the following properties are
+ immutable and MUST NOT be changed:
+
+ o id, createdAt
+
+ Additional SetErrors:
+
+ o "invalidParticipants": The participantIds list is invalid
+ (empty, contains non-existent users, etc.).
+
+ o "maxParticipantsExceeded": The conversation would exceed
+ the maximum number of participants allowed.
+
+ o "insufficientPermissions": The user does not have permission
+ to perform the requested action on this conversation.
+
+4.1.3. Conversation/changes
+
+ Standard "/changes" method as described in [RFC8620], Section 5.2.
+
+4.1.4. Conversation/query
+
+ Standard "/query" method as described in [RFC8620], Section 5.5.
+
+ Supported filter conditions:
+
+ o hasParticipant: "Id"
+ Matches conversations where the specified user is a participant.
+
+ o isArchived: "Boolean"
+ Matches conversations with the specified archived status.
+
+ o after: "UTCDate"
+ Matches conversations with lastMessageAt after this date.
+
+ o before: "UTCDate"
+ Matches conversations with lastMessageAt before this date.
+
+ o hasUnread: "Boolean"
+ If true, matches conversations with unreadCount > 0.
+ If false, matches conversations with unreadCount = 0.
+
+ Supported sort options:
+
+ o "lastMessageAt": Sort by the timestamp of the last message.
+ o "createdAt": Sort by conversation creation time.
+ o "title": Sort by conversation title (case-insensitive).
+ o "unreadCount": Sort by number of unread messages.
+
+ Default sort is "lastMessageAt desc".
+
+4.2. Message Methods
+
+4.2.1. Message/get
+
+ Standard "/get" method as described in [RFC8620], Section 5.1.
+
+ Additional errors:
+
+ None specific to this method.
+
+4.2.2. Message/set
+
+ Standard "/set" method as described in [RFC8620], Section 5.3.
+
+ When creating a new message, the following properties are
+ required in the create object:
+
+ o conversationId: Must reference an existing conversation.
+ o body: The message content.
+
+ The following properties MUST NOT be included when creating
+ a message:
+
+ o id, sentAt, receivedAt, editedAt, reactions, deliveryStatus,
+ readBy
+
+ The following properties are set by the server when creating:
+
+ o senderId: Set to the authenticated user's participant ID
+ in the specified conversation.
+
+ When updating a message, the following properties are
+ immutable and MUST NOT be changed:
+
+ o id, conversationId, senderId, sentAt, receivedAt,
+ isSystemMessage
+
+ Only the message sender can edit these properties:
+
+ o body, bodyType, attachments
+
+ The server MUST set editedAt when any editable property
+ is modified.
+
+ Message deletion is handled by setting isDeleted to true.
+ Servers MAY permanently delete message content after a
+ retention period.
+
+ Additional SetErrors:
+
+ o "conversationNotFound": The specified conversationId
+ does not exist.
+
+ o "notParticipant": The user is not a participant in
+ the specified conversation.
+
+ o "messageNotFound": The message to update does not exist.
+
+ o "cannotEditMessage": The user does not have permission
+ to edit this message (not the sender, message too old, etc.).
+
+ o "invalidReplyTo": The replyToMessageId references a
+ non-existent message or a message in a different conversation.
+
+ o "messageTooLarge": The message body exceeds maxMessageLength.
+
+4.2.3. Message/changes
+
+ Standard "/changes" method as described in [RFC8620], Section 5.2.
+
+4.2.4. Message/query
+
+ Standard "/query" method as described in [RFC8620], Section 5.5.
+
+ Supported filter conditions:
+
+ o inConversation: "Id"
+ Matches messages in the specified conversation.
+
+ o from: "Id"
+ Matches messages sent by the specified participant.
+
+ o after: "UTCDate"
+ Matches messages sent after this date.
+
+ o before: "UTCDate"
+ Matches messages sent before this date.
+
+ o hasAttachment: "Boolean"
+ If true, matches messages with attachments.
+
+ o text: "String"
+ Matches messages containing this text in the body
+ (case-insensitive substring search).
+
+ o isUnread: "Boolean"
+ If true, matches unread messages for this user.
+
+ o replyTo: "Id"
+ Matches messages that are replies to the specified message.
+
+ Supported sort options:
+
+ o "sentAt": Sort by message timestamp.
+ o "receivedAt": Sort by server receive timestamp.
+
+ Default sort is "sentAt asc".
+
+4.3. Participant Methods
+
+4.3.1. Participant/get
+
+ Standard "/get" method as described in [RFC8620], Section 5.1.
+
+4.3.2. Participant/set
+
+ Standard "/set" method as described in [RFC8620], Section 5.3.
+
+ When creating a new participant, the following properties are
+ required in the create object:
+
+ o conversationId: Must reference an existing conversation.
+ o userId: Must reference an existing user account.
+
+ The following properties MUST NOT be included when creating
+ a participant:
+
+ o id, joinedAt, lastActiveAt, isActive
+
+ When updating a participant, the following properties are
+ immutable and MUST NOT be changed:
+
+ o id, conversationId, userId, joinedAt
+
+ Only conversation owners/admins can modify:
+
+ o role, permissions
+
+ Additional SetErrors:
+
+ o "conversationNotFound": The specified conversationId
+ does not exist.
+
+ o "userNotFound": The specified userId does not exist.
+
+ o "alreadyParticipant": The user is already a participant
+ in this conversation.
+
+ o "cannotModifyParticipant": The user does not have
+ permission to modify participants in this conversation.
+
+ o "cannotRemoveSelf": The user cannot remove themselves
+ from the conversation (use conversation archiving instead).
+
+4.3.3. Participant/changes
+
+ Standard "/changes" method as described in [RFC8620], Section 5.2.
+
+4.4. Presence Methods
+
+4.4.1. Presence/get
+
+ Standard "/get" method as described in [RFC8620], Section 5.1.
+
+ Users can only retrieve presence information for users they
+ share conversations with, unless broader permissions are granted.
+
+ Additional errors:
+
+ o "cannotAccessPresence": The user does not have permission
+ to view presence information for the requested users.
+
+4.4.2. Presence/set
+
+ Standard "/set" method as described in [RFC8620], Section 5.3.
+
+ Users can only update their own presence information.
+
+ The following properties are immutable and MUST NOT be changed:
+
+ o userId, lastSeenAt, updatedAt
+
+ Additional SetErrors:
+
+ o "cannotSetOthersPresence": Attempted to set presence
+ for a user other than the authenticated user.
+
+5. Push Notifications
+
+ JCHAT extends JMAP push notifications to provide real-time
+ updates for chat events. The following state changes trigger
+ push notifications:
+
+ o New messages in conversations the user participates in
+ o Changes to conversation metadata
+ o Participant additions/removals
+ o Presence updates for users the client is interested in
+
+ Push subscription setup follows the standard JMAP push model
+ described in [RFC8620], Section 7.
+
+ The push notification payload includes the standard JMAP
+ StateChange object with the following chat-specific type
+ changes:
+
+ o "Conversation": Conversation state changes
+ o "Message": Message state changes
+ o "Participant": Participant state changes
+ o "Presence": Presence state changes
+
+ Clients SHOULD subscribe to push notifications for responsive
+ chat experience and battery efficiency on mobile devices.
+
+6. Security Considerations
+
+ JCHAT inherits the security model of JMAP [RFC8620] and adds
+ the following chat-specific considerations:
+
+ o Message Privacy: Messages are only accessible to conversation
+ participants. Servers MUST enforce participant membership
+ when processing requests.
+
+ o Participant Management: Only users with appropriate permissions
+ can add/remove participants or modify conversation settings.
+
+ o Presence Privacy: Presence information should only be shared
+ with users who share conversations or have explicit permission.
+
+ o Message Retention: Servers SHOULD provide configurable message
+ retention policies and honor deletion requests.
+
+ o Content Filtering: Servers MAY implement content filtering
+ for spam, abuse, or regulatory compliance.
+
+ o Rate Limiting: Servers SHOULD implement rate limiting for
+ message sending to prevent abuse.
+
+7. IANA Considerations
+
+ This document registers the JMAP Capability for chat as follows:
+
+ Capability Name: urn:ietf:params:jmap:chat
+ Specification document: This document
+ Intended use: COMMON
+ Change controller: IETF
+ Security and privacy considerations: See Section 6
+
+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,
+ <https://www.rfc-editor.org/info/rfc2119>.
+
+ [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>.
+
+ [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON)
+ Data Interchange Format", STD 90, RFC 8259,
+ DOI 10.17487/RFC8259, December 2017,
+ <https://www.rfc-editor.org/info/rfc8259>.
+
+ [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>.
+
+8.2. Informative References
+
+ [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed.,
+ "JavaScript Object Notation (JSON) Pointer", RFC 6901,
+ DOI 10.17487/RFC6901, April 2013,
+ <https://www.rfc-editor.org/info/rfc6901>.
+
+Author's Address
+
+ Calvin Smith
+ Fastmail
+
+ Email: calvin@fastmail.com