package csp_e2e

Mouse Melon logoGet desktop application:
View/edit binary Protocol Buffers messages

message DeleteMessage

csp-e2e.proto:341

Remove an existing message. Note: This is a soft-security feature at best and it applies a best effort approach, meaning that it relies on some level of good will on the receiving end. A malicious receiver can easily persist a message prior to removal by e.g. making a screenshot, forwarding it, changing the date, explicitly saving it (if it contains media), etc. **Properties (1:1)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - Edit applies to: N/A - Deletable by: N/A (obviously) - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: N/A **Properties (Group)**: - Kind: Group - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No - Edit applies to: N/A - Deletable by: N/A (obviously) - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: If capture is enabled The following steps must be invoked when the user wants to delete a 1:1 message: 1. If the sender or the receiver do not have `DELETE_MESSAGE_SUPPORT`, disallow removal and abort these steps. 2. Run the _Common Delete Message Preflight Steps_. 3. Let `deleted-at` be the current timestamp. 4. Run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `deleted-at`, - to construct a `DeleteMessage` message. 5. Replace the referred message with a message informing the user that the referred message of the user has been removed at `deleted-at`.² The following steps must be invoked when the user wants to delete a group message. 1. If the group is marked as _left_, disallow removal and abort these steps. 2. If the sender or all of the group members do not have `DELETE_MESSAGE_SUPPORT`, disallow removal and abort these steps. 3. Run the _Common Delete Message Preflight Steps_. 4. If any of the group members do not have `DELETE_MESSAGE_SUPPORT`, notify the user that the affected contacts will continue to see the message. 5. Let `deleted-at` be the current timestamp. 6. Run the _Group Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `deleted-at`, - to construct a `DeleteMessage` message (wrapped by [`group-member-container`](ref:e2e.group-member-container)). 7. Replace the referred message with a message informing the user that the referred message of the user has been removed at `deleted-at`.² The following steps are defined as the _Common Delete Message Preflight Steps_: 1. Let `message` be the referred message. 2. If the user is not the original sender of `message`, disallow removal and abort these steps. 3. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow removal and abort these steps.¹ When reflected from another device as an incoming or outgoing 1:1 message: 1. Run the _Common Delete Message Receive Steps_. When receiving this message as a 1:1 message: 1. Run the _Common Delete Message Receive Steps_. When reflected from another device as an incoming or outgoing group message: 1. Run the _Common Delete Message Receive Steps_. When receiving this message as a group message (wrapped by [`group-member-container`](ref:e2e.group-member-container)): 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message has been discarded, abort these steps. 2. Run the _Common Delete Message Receive Steps_. The following steps are defined as the _Common Delete Message Receive Steps_: 1. Lookup the message with `message_id` originally sent by the sender within the associated conversation and let `message` be the result. 2. If `referred-message` is not defined or the sender is not the original sender of `message`, discard the message and abort these steps. 3. If `referred-message` is not deletable (see the associated _Deletable by_ property), discard the message and abort these steps. 4. Replace `referred-message` with a message informing the user that the message of the sender has been removed at the message's (the `DeleteMessage`'s) `created-at`.² ¹: For simplicity, the time constraint is applied on the sender side only. The receiver will always accept a request to delete a message. This is deemed acceptable considering this is just barely a soft-security feature. ²: All references to a removed message (e.g. quotes) must be updated as well, so that the message content is no longer visible. An implementation should also try to withdraw or update any notification created for a removed message.

message EditMessage

csp-e2e.proto:202

Edit an existing message (e.g. a text message or a media message caption). **Properties (1:1)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - Edit applies to: N/A (obviously) - Deletable by: N/A - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: N/A **Properties (Group)**: - Kind: Group - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No - Edit applies to: N/A (obviously) - Deletable by: N/A - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: If capture is enabled The following steps must be invoked when the user wants to edit a 1:1 message: 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, disallow editing and abort these steps. 2. Run the _Common Edit Message Enter Steps_. 3. Allow the user to edit the referred message. The following steps must be invoked when the user wants to edit a group message: 1. If the group is marked as _left_, disallow editing and abort these steps. 2. If the sender or all of the group members do not have `EDIT_MESSAGE_SUPPORT`, disallow editing and abort these steps. 3. Run the _Common Edit Message Enter Steps_. 4. If any of the group members do not have `EDIT_MESSAGE_SUPPORT`, notify the user that the affected contacts will not receive the edited content. 5. Allow the user to edit the referred message. The following steps are defined as the _Common Edit Message Enter Steps_: 1. Let `message` be the referred message. 2. If the user is not the original sender of `message`, disallow editing and abort these steps. 3. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow editing and abort these steps.¹ The following steps must be invoked when the user wants to submit an edited 1:1 message. 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, discard the edited message and abort these steps. 2. Run the _Common Edit Message Submit Preflight Steps_. 3. Let `edited-at` be the current timestamp. 4. Run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `edited-at`, - to construct an `EditMessage` message. 5. Edit the referred message as defined by the associated _Edit applies to_ property and add an indicator to the referred message, informing the user that the referred message has been edited by the user at `edited-at`. The following steps must be invoked when the user wants to submit an edited group message. 1. If the group is marked as _left_, discard the edited message and abort these steps. 2. If the sender or all of the group members do not have `EDIT_MESSAGE_SUPPORT`, discard the edited message and abort these steps. 3. Run the _Common Edit Message Submit Preflight Steps_. 4. Let `edited-at` be the current timestamp. 5. Run the _Group Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `edited-at`, - to construct an `EditMessage` message (wrapped by [`group-member-container`](ref:e2e.group-member-container)). 6. Edit the referred message as defined by the associated _Edit applies to_ property and add an indicator to the referred message, informing the user that the referred message has been edited by the user at `edited-at`. The following steps are defined as the _Common Edit Message Submit Preflight Steps_: 1. Lookup the message with `message_id` originally sent by the sender within the associated conversation and let `message` be the result. 2. If `message` is no longer defined, discard the edited message and abort these steps. 3. If the content of `message` is identical to the edited message, discard the edited message and abort these steps. When reflected from another device as an incoming or outgoing 1:1 message: 1. Run the _Common Edit Message Receive Steps_. When receiving this message as a 1:1 message: 1. Run the _Common Edit Message Receive Steps_. When reflected from another device as an incoming or outgoing group message: 1. Run the _Common Edit Message Receive Steps_. When receiving this message as a group message (wrapped by [`group-member-container`](ref:e2e.group-member-container)): 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message has been discarded, abort these steps. 2. Run the _Common Edit Message Receive Steps_. The following steps are defined as the _Common Edit Message Receive Steps_: 1. Lookup the message with `message_id` originally sent by the sender within the associated conversation and let `referred-message` be the result. 2. If `referred-message` is not defined or the sender is not the original sender of `referred-message`, discard the message and abort these steps.² 3. If `referred-message` is not editable (see the associated _Edit applies to_ property), discard the message and abort these steps. 4. Edit `referred-message` as defined by the associated _Edit applies to_ property and add an indicator to `referred-message`, informing the user that the message has been edited by the sender at the message's (the `EditMessage`'s) `created-at`. ¹: For simplicity, the time constraint is applied on the sender side only. The receiver will always accept a request to edit a message. This is deemed acceptable considering this is not a security feature. ²: Implementations do not track the group member setup at the time a message was received. Therefore, an edited message is always sent to the **current** group member setup, including any group members that weren't part of the group when the message was sent. However, any ordinary client will discard `EditMessage` for unknown messages. This leak is not great but considered acceptable for now.

message GroupCallStart

csp-e2e.proto:408

Announces and immediately starts a group call. **Properties**: - Kind: Group - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: Yes - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: TODO(SE-508) - Bump _last update_: TODO(SE-508) - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No - When rejected: N/A¹ - Edit applies to: N/A - Deletable by: N/A - Send to Threema Gateway ID group creator: If capture is enabled ¹: For the group creator it will be handled as if `group-sync-request` was received, re-sending a `GroupCallStart` if still ongoing, implicitly triggered by FS `Reject` receive steps. When the user wants to create a new group call or join an existing group call, run the steps outlined in the _Create or Join_ section of the Group Call Protocol. When reflected from another device as an incoming or outgoing message: 1. Run the _Common Group Call Start Receive Steps_. When receiving this message: 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message has been discarded, abort these steps. 2. Run the _Common Group Call Start Receive Steps_. The following steps are defined as the _Common Group Call Start Receive Steps_: 1. If the hostname of `sfu_base_url` does not use the scheme `https` or does not end with one of the set of [_Allowed SFU Hostname Suffixes_](ref:group-calls#obtain-sfu-information), log a warning, discard the message and abort these steps. 2. Let `running` be the list of group calls that are currently considered running within the group. 3. If another call with the same GCK exists in `running`, log a warning, discard the message and abort these steps. 4. Add the received call to the list of group calls that are currently considered running (even if `protocol_version` is unsupported¹). 5. Start a task to run the _Group Call Refresh Steps_.² ¹: Adding unsupported `protocol_version`s allows the user to join an ongoing call after an app update where support for `protocol_version` has been added. ²: This ensures that the user automatically switches to the chosen call if it is currently participating in a group call of this group.

message GroupJoinRequest

csp-e2e.proto:664

Request joining a group. This message is sent to the administrator of a group. The required information is provided by a `GroupInvite` URL payload. **Properties**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: Yes - Implicit _direct_ contact creation: Yes - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - When rejected: N/A (ignored) - Edit applies to: N/A - Deletable by: User only - Send to Threema Gateway ID group creator: N/A When receiving this message: 1. Look up the corresponding group invitation by the token. 2. If the group invitation could not be found, discard the message and abort these steps. 3. If the sender is already part of the group, send an accept response and then respond as if the sender had sent a `group-sync-request` (i.e. send a `group-setup`, `group-name`, etc.). Finally, abort these steps. 4. If the group name does not match the name in the originally sent group invitation, discard the message and abort these steps. 5. If the group invitation has expired, send the respective response and abort these steps. 6. If the group invitation requires the admin to accept the request, show this information in the user interface and pause these steps until the user manually confirmed of rejected the request. Note that the date of the decision is allowed to extend beyond the expiration date of the group invitation. Continue with the following sub-steps once the user made a decision on the request: 1. If the user manually rejected the request, send the respective response and abort these steps. 7. If the group is full, send the respective response and abort these steps. 8. Send an accept response. 9. Add the sender of the group invitation request to the group and follow the group protocol from there.

message GroupJoinResponse

csp-e2e.proto:713

Response sent by the admin of a group towards a sender of a valid group join request. **Properties**: - Kind: 1:1 - Flags: None - User profile distribution: Yes - Exempt from blocking: Yes - Implicit _direct_ contact creation: Yes - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - When rejected: N/A (ignored) - Edit applies to: N/A - Deletable by: N/A - Send to Threema Gateway ID group creator: N/A When receiving this message: 1. Look up the corresponding group join request by the token and the sender's Threema ID as the administrator's Threema ID. 2. If the group join request could not be found, discard the message and abort these steps. 3. Mark the group join request as accepted or (automatically) rejected by the given response type. 4. If the group join request has been accepted, remember the group id in order to be able to map an incoming `group-setup` to the group.

message GroupJoinResponse.Response

csp-e2e.proto:718

Response of the admin

Used in: GroupJoinResponse

message GroupJoinResponse.Response.Accept

csp-e2e.proto:720

Accept a group invite request

Used in: Response

message MessageMetadata

csp-e2e.proto:17

Metadata sent within a CSP payload `message-with-metadata-box` struct.

message Reaction

csp-e2e.proto:602

React to a message. **Properties (1:1)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No, that would be silly! - When rejected: N/A (ignored) - Edit applies to: N/A (can withdraw and apply with another `Reaction`) - Deletable by: N/A (can withdraw with another `Reaction`) - Send to Threema Gateway ID group creator: N/A **Properties (Group)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No, that would be silly! - When rejected: N/A (ignored) - Edit applies to: N/A (can withdraw and apply with another `Reaction`) - Deletable by: N/A (can withdraw with another `Reaction`) - Send to Threema Gateway ID group creator: If capture is enabled When the user submits a reaction in a 1:1 conversation: 1. Let `reaction` be the reaction to be applied to or withdrawn from a referred message which must contain a single fully-qualified [emoji codepoint sequence that is part of the currently supported Unicode standard][emoji-test.txt]. 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let `legacy-reaction` be the result. 3. If `legacy-reaction` is not defined and the sender or the receiver does not have `REACTION_SUPPORT`, log a warning and abort these steps.¹ 4. Let `reacted-at` be the current timestamp. 5. If both sender and receiver have `REACTION_SUPPORT`, run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `reacted-at`, - to construct a `Reaction` message from `reaction`. 6. If the sender or the receiver does not have `REACTION_SUPPORT`, run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `reacted-at`, - to construct the `legacy-reaction`. 7. Apply `reaction` (i.e. apply or withdraw) to the referred message with the `reacted-at` timestamp. When the user submits a reaction in a group conversation: 1. Let `reaction` be the reaction to be applied to or withdrawn from a referred message which must contain a single fully-qualified [emoji codepoint sequence that is part of the currently supported Unicode standard][emoji-test.txt]. 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let `legacy-reaction` be the result. 3. If `legacy-reaction` is not defined: 1. If the sender does not have `REACTION_SUPPORT`, log a warning and abort these steps.² 2. If all of the group members do not have `REACTION_SUPPORT`, log a warning and and abort these steps.² 3. If any of the group members do not have `REACTION_SUPPORT`, notify the user that the affected contacts will not receive the reaction. 4. Let `reacted-at` be the current timestamp. 5. Run the _Group Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `reacted-at`, - to construct a _canonical_ `Reaction` message from `reaction`, - to construct a _specific_ message in the following way: 1. Let `receiver` be the specific receiver. 2. If the `receiver` does not have `REACTION_SUPPORT` and `legacy-reaction` is defined, return the `legacy-reaction` (wrapped by [`group-member-container`](ref:e2e.group-member-container)). 3. Construct and return the _canonical_ `Reaction` message from `reaction` (wrapped by [`group-member-container`](ref:e2e.group-member-container)).³ 6. Apply `reaction` (i.e. apply or withdraw) to the referred message with the `reacted-at` timestamp. The following steps are defined as the _Legacy Reaction Mapping Steps_: 1. If `action` is of variant `apply`: 1. If `action.apply` equals one of the following codepoint sequences, return a `e2e.delivery-receipt` of type _acknowledge_ (0x03): - `1F44D` (👍) - `1F44D 1F3FB` (👍🏻) - `1F44D 1F3FC` (👍🏼) - `1F44D 1F3FD` (👍🏽) - `1F44D 1F3FE` (👍🏾) - `1F44D 1F3FF` (👍🏿) 2. If `action.apply` equals one of the following codepoint sequences, return a `e2e.delivery-receipt` of type _decline_ (0x04): - `1F44E` (👎) - `1F44E 1F3FB` (👎🏻) - `1F44E 1F3FC` (👎🏼) - `1F44E 1F3FD` (👎🏽) - `1F44E 1F3FE` (👎🏾) - `1F44E 1F3FF` (👎🏿) 2. Return no message. When reflected from another device as an incoming or outgoing 1:1 message: 1. Run the _Common Reaction Receive Steps_. When receiving this message: 1. Run the _Common Reaction Receive Steps_. When receiving this message (wrapped by [`group-member-container`](ref:e2e.group-member-container)): 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the reaction message has been discarded, abort these steps. 1. Run the _Common Reaction Receive Steps_. The following steps are defined as the _Common Reaction Receive Steps_: 1. Lookup the referred message with `message_id` within the associated conversation and let `referred-message` be the result. 2. If `referred-message` is not defined, discard the message and abort these steps. 3. If `referred-message` is not reactable (see the associated _Reactions_ property), discard the message and abort these steps. 4. If `action` is of variant `apply`: 1. If `apply` contains more than 64 bytes, discard the message and abort these steps. 2. Decode `apply` to a UTF-8 string. If the string is empty, discard the message and abort these steps. 3. Apply (or re-apply) the resulting emoji from the sender to `referred-message` with the message's (the `Reaction`'s) `created-at` timestamp used for the time of reaction.⁴⁵ 5. If `action` is of variant `withdraw`: 1. If `withdraw` contains more than 64 bytes, discard the message and abort these steps. 2. Decode `withdraw` to a UTF-8 string. If the string is empty, discard the message and abort these steps. 3. Remove the resulting emoji reaction from the sender for `message`.⁴⁵ ¹: The UI should not allow to create non-legacy reactions in 1:1 conversations with a sender or receiver that does not have `REACTION_SUPPORT`. ²: The UI should not allow to create non-legacy reactions in group conversations with a sender that does not have `REACTION_SUPPORT` or when all other group members don't have `REACTION_SUPPORT`. ³: In case the reaction could not be mapped to a legacy reaction, this results in a `Reaction` message being sent to group members that currently do not support reactions. This is intentional. ⁴: Note that the _apply_ mechanism is additive, meaning multiple reactions from the same sender are allowed on a single message. This is why the _withdraw_ mechanism is needed which removes a specific reaction. On the other hand, a deprecated `e2e.delivery-receipt` will replace all existing reactions of the sender at once (including these new-style reactions). ⁵: The UI should display a placeholder (�) for unknown emojis, meaining those which are not a single fully-qualified [emoji codepoint sequence that is part of the currently supported Unicode standard][emoji-test.txt]. But the individual code sequences still have individual display buckets. [emoji-test.txt]: https://www.unicode.org/Public/emoji/latest/emoji-test.txt