csp-e2e.proto 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. // ## End-to-End Encrypted Messages (Supplementary)
  2. //
  3. // This is a supplementary section to the corresponding structbuf section
  4. // with newer messages that use protobuf instead of structbuf. All defined
  5. // messages here follow the same logic.
  6. syntax = "proto3";
  7. package csp_e2e;
  8. option java_package = "ch.threema.protobuf.csp.e2e";
  9. option java_multiple_files = true;
  10. import "common.proto";
  11. // Metadata sent within a CSP payload `message-with-metadata-box` struct.
  12. message MessageMetadata {
  13. // Padding that is ignored by the receiver.
  14. // Recommended to be chosen such that the total length of padding + nickname
  15. // is at least 16 bytes. May be empty if the nickname is long enough.
  16. bytes padding = 1;
  17. // Unique message ID. Must match the message ID of the outer struct
  18. // (i.e. `message-with-metadata-box.message-id`).
  19. fixed64 message_id = 3;
  20. // Unix-ish timestamp in milliseconds for when the message has been created.
  21. //
  22. // Messages sent in a group must have the same timestamp for each group
  23. // member.
  24. uint64 created_at = 4;
  25. // Nickname
  26. //
  27. // Should be sent when the associate message requires _user profile
  28. // distribution_.
  29. //
  30. // When the user cleared its nickname, send an empty string. Do not send the
  31. // user's Threema ID (i.e. process data).
  32. //
  33. // Recommended to not exceed 32 grapheme clusters. Should not contain
  34. // whitespace characters at the beginning or the end of string.
  35. optional string nickname = 2;
  36. }
  37. // Edit an existing message (e.g. a text message or a media message caption).
  38. //
  39. // **Properties (1:1)**:
  40. // - Kind: 1:1
  41. // - Flags:
  42. // - `0x01`: Send push notification.
  43. // - User profile distribution: No
  44. // - Exempt from blocking: No
  45. // - Implicit _direct_ contact creation: No
  46. // - Protect against replay: Yes
  47. // - Unarchive: No
  48. // - Bump _last update_: No
  49. // - Reflect:
  50. // - Incoming: Yes
  51. // - Outgoing: Yes
  52. // - _Sent_ update: No
  53. // - Delivery receipts: No
  54. // - Reactions: No
  55. // - Edit applies to: N/A (obviously)
  56. // - Deletable by: N/A
  57. // - When rejected: N/A (ignored)
  58. // - Send to Threema Gateway ID group creator: N/A
  59. //
  60. // **Properties (Group)**:
  61. // - Kind: Group
  62. // - Flags:
  63. // - `0x01`: Send push notification.
  64. // - User profile distribution: No
  65. // - Exempt from blocking: No
  66. // - Implicit _direct_ contact creation: No
  67. // - Protect against replay: Yes
  68. // - Unarchive: No
  69. // - Bump _last update_: No
  70. // - Reflect:
  71. // - Incoming: Yes
  72. // - Outgoing: Yes
  73. // - _Sent_ update: No
  74. // - Delivery receipts: N/A
  75. // - Reactions: No
  76. // - Edit applies to: N/A (obviously)
  77. // - Deletable by: N/A
  78. // - When rejected: N/A (ignored)
  79. // - Send to Threema Gateway ID group creator: If capture is enabled
  80. //
  81. // The following steps must be invoked when the user wants to edit a 1:1
  82. // message:
  83. //
  84. // 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, disallow
  85. // editing and abort these steps.
  86. // 2. Run the _Common Edit Message Enter Steps_.
  87. // 3. Allow the user to edit the referred message.
  88. //
  89. // The following steps must be invoked when the user wants to edit a group
  90. // message:
  91. //
  92. // 1. If the group is marked as _left_, disallow editing and abort these steps.
  93. // 2. If the sender or all of the group members do not have
  94. // `EDIT_MESSAGE_SUPPORT`, disallow editing and abort these steps.
  95. // 3. Run the _Common Edit Message Enter Steps_.
  96. // 4. If any of the group members do not have `EDIT_MESSAGE_SUPPORT`, notify the
  97. // user that the affected contacts will not receive the edited content.
  98. // 5. Allow the user to edit the referred message.
  99. //
  100. // The following steps are defined as the _Common Edit Message Enter Steps_:
  101. //
  102. // 1. Let `message` be the referred message.
  103. // 2. If the user is not the original sender of `message`, disallow editing and
  104. // abort these steps.
  105. // 3. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow
  106. // editing and abort these steps.¹
  107. //
  108. // The following steps must be invoked when the user wants to submit an edited
  109. // 1:1 message.
  110. //
  111. // 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, discard
  112. // the edited message and abort these steps.
  113. // 2. Run the _Common Edit Message Submit Preflight Steps_.
  114. // 3. Let `edited-at` be the current timestamp.
  115. // 4. Run the _1:1 Messages Submit Steps_ with `messages` set from the following
  116. // properties:
  117. // - `created-at` set to `edited-at`,
  118. // - to construct an `EditMessage` message.
  119. // 5. Edit the referred message as defined by the associated _Edit applies to_
  120. // property and add an indicator to the referred message, informing the user
  121. // that the referred message has been edited by the user at `edited-at`.
  122. //
  123. // The following steps must be invoked when the user wants to submit an edited
  124. // group message.
  125. //
  126. // 1. If the group is marked as _left_, discard the edited message and abort
  127. // these steps.
  128. // 2. If the sender or all of the group members do not have
  129. // `EDIT_MESSAGE_SUPPORT`, discard the edited message and abort these steps.
  130. // 3. Run the _Common Edit Message Submit Preflight Steps_.
  131. // 4. Let `edited-at` be the current timestamp.
  132. // 5. Run the _Group Messages Submit Steps_ with `messages` set from the
  133. // following properties:
  134. // - `created-at` set to `edited-at`,
  135. // - to construct an `EditMessage` message (wrapped by
  136. // [`group-member-container`](ref:e2e.group-member-container)).
  137. // 6. Edit the referred message as defined by the associated _Edit applies to_
  138. // property and add an indicator to the referred message, informing the user
  139. // that the referred message has been edited by the user at `edited-at`.
  140. //
  141. // The following steps are defined as the _Common Edit Message Submit Preflight
  142. // Steps_:
  143. //
  144. // 1. Lookup the message with `message_id` originally sent by the sender within
  145. // the associated conversation and let `message` be the result.
  146. // 2. If `message` is no longer defined, discard the edited message and abort
  147. // these steps.
  148. // 3. If the content of `message` is identical to the edited message, discard
  149. // the edited message and abort these steps.
  150. //
  151. // When reflected from another device as an incoming or outgoing 1:1 message:
  152. //
  153. // 1. Run the _Common Edit Message Receive Steps_.
  154. //
  155. // When receiving this message as a 1:1 message:
  156. //
  157. // 1. Run the _Common Edit Message Receive Steps_.
  158. //
  159. // When reflected from another device as an incoming or outgoing group message:
  160. //
  161. // 1. Run the _Common Edit Message Receive Steps_.
  162. //
  163. // When receiving this message as a group message (wrapped by
  164. // [`group-member-container`](ref:e2e.group-member-container)):
  165. //
  166. // 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message
  167. // has been discarded, abort these steps.
  168. // 2. Run the _Common Edit Message Receive Steps_.
  169. //
  170. // The following steps are defined as the _Common Edit Message Receive Steps_:
  171. //
  172. // 1. Lookup the message with `message_id` originally sent by the sender within
  173. // the associated conversation and let `referred-message` be the result.
  174. // 2. If `referred-message` is not defined or the sender is not the original
  175. // sender of `referred-message`, discard the message and abort these steps.²
  176. // 3. If `referred-message` is not editable (see the associated _Edit applies
  177. // to_ property), discard the message and abort these steps.
  178. // 4. Edit `referred-message` as defined by the associated _Edit applies to_
  179. // property and add an indicator to `referred-message`, informing the user
  180. // that the message has been edited by the sender at the message's (the
  181. // `EditMessage`'s) `created-at`.
  182. //
  183. // ¹: For simplicity, the time constraint is applied on the sender side only.
  184. // The receiver will always accept a request to edit a message. This is deemed
  185. // acceptable considering this is not a security feature.
  186. //
  187. // ²: Implementations do not track the group member setup at the time a message
  188. // was received. Therefore, an edited message is always sent to the **current**
  189. // group member setup, including any group members that weren't part of the
  190. // group when the message was sent. However, any ordinary client will discard
  191. // `EditMessage` for unknown messages. This leak is not great but considered
  192. // acceptable for now.
  193. message EditMessage {
  194. // Unique ID of the referred message to be edited.
  195. fixed64 message_id = 1;
  196. // Text (or caption) to update the referred message with. Should be ≤ 6000
  197. // bytes.
  198. string text = 2;
  199. }
  200. // Remove an existing message.
  201. //
  202. // Note: This is a soft-security feature at best and it applies a best effort
  203. // approach, meaning that it relies on some level of good will on the receiving
  204. // end. A malicious receiver can easily persist a message prior to removal by
  205. // e.g. making a screenshot, forwarding it, changing the date, explicitly saving
  206. // it (if it contains media), etc.
  207. //
  208. // **Properties (1:1)**:
  209. // - Kind: 1:1
  210. // - Flags:
  211. // - `0x01`: Send push notification.
  212. // - User profile distribution: No
  213. // - Exempt from blocking: No
  214. // - Implicit _direct_ contact creation: No
  215. // - Protect against replay: Yes
  216. // - Unarchive: No
  217. // - Bump _last update_: No
  218. // - Reflect:
  219. // - Incoming: Yes
  220. // - Outgoing: Yes
  221. // - _Sent_ update: No
  222. // - Delivery receipts: No
  223. // - Reactions: No
  224. // - Edit applies to: N/A
  225. // - Deletable by: N/A (obviously)
  226. // - When rejected: N/A (ignored)
  227. // - Send to Threema Gateway ID group creator: N/A
  228. //
  229. // **Properties (Group)**:
  230. // - Kind: Group
  231. // - Flags:
  232. // - `0x01`: Send push notification.
  233. // - User profile distribution: No
  234. // - Exempt from blocking: No
  235. // - Implicit _direct_ contact creation: No
  236. // - Protect against replay: Yes
  237. // - Unarchive: No
  238. // - Bump _last update_: No
  239. // - Reflect:
  240. // - Incoming: Yes
  241. // - Outgoing: Yes
  242. // - _Sent_ update: No
  243. // - Delivery receipts: N/A
  244. // - Reactions: No
  245. // - Edit applies to: N/A
  246. // - Deletable by: N/A (obviously)
  247. // - When rejected: N/A (ignored)
  248. // - Send to Threema Gateway ID group creator: If capture is enabled
  249. //
  250. // The following steps must be invoked when the user wants to delete a 1:1
  251. // message:
  252. //
  253. // 1. If the sender or the receiver do not have `DELETE_MESSAGE_SUPPORT`,
  254. // disallow removal and abort these steps.
  255. // 2. Run the _Common Delete Message Preflight Steps_.
  256. // 3. Let `deleted-at` be the current timestamp.
  257. // 4. Run the _1:1 Messages Submit Steps_ with `messages` set from the following
  258. // properties:
  259. // - `created-at` set to `deleted-at`,
  260. // - to construct a `DeleteMessage` message.
  261. // 5. Replace the referred message with a message informing the user that the
  262. // referred message of the user has been removed at `deleted-at`.²
  263. //
  264. // The following steps must be invoked when the user wants to delete a group
  265. // message.
  266. //
  267. // 1. If the group is marked as _left_, disallow removal and abort these steps.
  268. // 2. If the sender or all of the group members do not have
  269. // `DELETE_MESSAGE_SUPPORT`, disallow removal and abort these steps.
  270. // 3. Run the _Common Delete Message Preflight Steps_.
  271. // 4. If any of the group members do not have `DELETE_MESSAGE_SUPPORT`, notify
  272. // the user that the affected contacts will continue to see the message.
  273. // 5. Let `deleted-at` be the current timestamp.
  274. // 6. Run the _Group Messages Submit Steps_ with `messages` set from the
  275. // following properties:
  276. // - `created-at` set to `deleted-at`,
  277. // - to construct a `DeleteMessage` message (wrapped by
  278. // [`group-member-container`](ref:e2e.group-member-container)).
  279. // 7. Replace the referred message with a message informing the user that the
  280. // referred message of the user has been removed at `deleted-at`.²
  281. //
  282. // The following steps are defined as the _Common Delete Message Preflight
  283. // Steps_:
  284. //
  285. // 1. Let `message` be the referred message.
  286. // 2. If the user is not the original sender of `message`, disallow removal and
  287. // abort these steps.
  288. // 3. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow
  289. // removal and abort these steps.¹
  290. //
  291. // When reflected from another device as an incoming or outgoing 1:1 message:
  292. //
  293. // 1. Run the _Common Delete Message Receive Steps_.
  294. //
  295. // When receiving this message as a 1:1 message:
  296. //
  297. // 1. Run the _Common Delete Message Receive Steps_.
  298. //
  299. // When reflected from another device as an incoming or outgoing group message:
  300. //
  301. // 1. Run the _Common Delete Message Receive Steps_.
  302. //
  303. // When receiving this message as a group message (wrapped by
  304. // [`group-member-container`](ref:e2e.group-member-container)):
  305. //
  306. // 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message
  307. // has been discarded, abort these steps.
  308. // 2. Run the _Common Delete Message Receive Steps_.
  309. //
  310. // The following steps are defined as the _Common Delete Message Receive Steps_:
  311. //
  312. // 1. Lookup the message with `message_id` originally sent by the sender within
  313. // the associated conversation and let `message` be the result.
  314. // 2. If `referred-message` is not defined or the sender is not the original
  315. // sender of `message`, discard the message and abort these steps.
  316. // 3. If `referred-message` is not deletable (see the associated _Deletable by_
  317. // property), discard the message and abort these steps.
  318. // 4. Replace `referred-message` with a message informing the user that the
  319. // message of the sender has been removed at the message's (the
  320. // `DeleteMessage`'s) `created-at`.²
  321. //
  322. // ¹: For simplicity, the time constraint is applied on the sender side only.
  323. // The receiver will always accept a request to delete a message. This is deemed
  324. // acceptable considering this is just barely a soft-security feature.
  325. //
  326. // ²: All references to a removed message (e.g. quotes) must be updated as well,
  327. // so that the message content is no longer visible. An implementation should
  328. // also try to withdraw or update any notification created for a removed
  329. // message.
  330. message DeleteMessage {
  331. // Unique ID of the referred message to be removed.
  332. fixed64 message_id = 1;
  333. }
  334. // Announces and immediately starts a group call.
  335. //
  336. // **Properties**:
  337. // - Kind: Group
  338. // - Flags:
  339. // - `0x01`: Send push notification.
  340. // - User profile distribution: Yes
  341. // - Exempt from blocking: Yes
  342. // - Implicit _direct_ contact creation: No
  343. // - Protect against replay: Yes
  344. // - Unarchive: TODO(SE-508)
  345. // - Bump _last update_: TODO(SE-508)
  346. // - Reflect:
  347. // - Incoming: Yes
  348. // - Outgoing: Yes
  349. // - _Sent_ update: No
  350. // - Delivery receipts: N/A
  351. // - Reactions: No
  352. // - When rejected: N/A¹
  353. // - Edit applies to: N/A
  354. // - Deletable by: N/A
  355. // - Send to Threema Gateway ID group creator: If capture is enabled
  356. //
  357. // ¹: For the group creator it will be handled as if `group-sync-request` was
  358. // received, re-sending a `GroupCallStart` if still ongoing, implicitly
  359. // triggered by FS `Reject` receive steps.
  360. //
  361. // When the user wants to create a new group call or join an existing group
  362. // call, run the steps outlined in the _Create or Join_ section of the Group
  363. // Call Protocol.
  364. //
  365. // When reflected from another device as an incoming or outgoing message:
  366. //
  367. // 1. Run the _Common Group Call Start Receive Steps_.
  368. //
  369. // When receiving this message:
  370. //
  371. // 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message
  372. // has been discarded, abort these steps.
  373. // 2. Run the _Common Group Call Start Receive Steps_.
  374. //
  375. // The following steps are defined as the _Common Group Call Start Receive
  376. // Steps_:
  377. //
  378. // 1. If the hostname of `sfu_base_url` does not use the scheme `https` or does
  379. // not end with one of the set of [_Allowed SFU Hostname
  380. // Suffixes_](ref:group-calls#obtain-sfu-information), log a warning, discard
  381. // the message and abort these steps.
  382. // 2. Let `running` be the list of group calls that are currently considered
  383. // running within the group.
  384. // 3. If another call with the same GCK exists in `running`, log a warning,
  385. // discard the message and abort these steps.
  386. // 4. Add the received call to the list of group calls that are currently
  387. // considered running (even if `protocol_version` is unsupported¹).
  388. // 5. Start a task to run the _Group Call Refresh Steps_.²
  389. //
  390. // ¹: Adding unsupported `protocol_version`s allows the user to join an ongoing
  391. // call after an app update where support for `protocol_version` has been
  392. // added.
  393. //
  394. // ²: This ensures that the user automatically switches to the chosen call if it
  395. // is currently participating in a group call of this group.
  396. message GroupCallStart {
  397. // Protocol version used for group calls of this group. The current version
  398. // number is `1`.
  399. //
  400. // Note: This is a _major_ version and may only be increased in case of
  401. // breaking changes due to the significant UX impact this has when running the
  402. // _Common Group Receive Steps_ (i.e. only calls with supported protocol
  403. // versions can be _chosen_).
  404. uint32 protocol_version = 1;
  405. // The secret Group Call Key (`GCK`) used for this call.
  406. bytes gck = 2;
  407. // The base URL of the SFU, used to join or peek the call.
  408. string sfu_base_url = 3;
  409. }
  410. // React to a message.
  411. //
  412. // **Properties (1:1)**:
  413. // - Kind: 1:1
  414. // - Flags:
  415. // - `0x01`: Send push notification.
  416. // - User profile distribution: Yes
  417. // - Exempt from blocking: No
  418. // - Implicit _direct_ contact creation: No
  419. // - Protect against replay: Yes
  420. // - Reflect:
  421. // - Incoming: Yes
  422. // - Outgoing: Yes
  423. // - _Sent_ update: No
  424. // - Delivery receipts: No
  425. // - Reactions: No, that would be silly!
  426. // - When rejected: N/A (ignored)
  427. // - Edit applies to: N/A (can withdraw and apply with another `Reaction`)
  428. // - Deletable by: N/A (can withdraw with another `Reaction`)
  429. // - Send to Threema Gateway ID group creator: N/A
  430. //
  431. // **Properties (Group)**:
  432. // - Kind: 1:1
  433. // - Flags:
  434. // - `0x01`: Send push notification.
  435. // - User profile distribution: Yes
  436. // - Exempt from blocking: No
  437. // - Implicit _direct_ contact creation: No
  438. // - Protect against replay: Yes
  439. // - Reflect:
  440. // - Incoming: Yes
  441. // - Outgoing: Yes
  442. // - _Sent_ update: No
  443. // - Delivery receipts: N/A
  444. // - Reactions: No, that would be silly!
  445. // - When rejected: N/A (ignored)
  446. // - Edit applies to: N/A (can withdraw and apply with another `Reaction`)
  447. // - Deletable by: N/A (can withdraw with another `Reaction`)
  448. // - Send to Threema Gateway ID group creator: If capture is enabled
  449. //
  450. // When the user submits a reaction in a 1:1 conversation:
  451. //
  452. // 1. Let `reaction` be the reaction to be applied to or withdrawn from a
  453. // referred message which must contain a single fully-qualified [emoji
  454. // codepoint sequence that is part of the currently supported Unicode
  455. // standard][emoji-test.txt].
  456. // 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let
  457. // `legacy-reaction` be the result.
  458. // 3. If `legacy-reaction` is not defined and the sender or the receiver does
  459. // not have `REACTION_SUPPORT`, log a warning and abort these steps.¹
  460. // 4. Let `reacted-at` be the current timestamp.
  461. // 5. If both sender and receiver have `REACTION_SUPPORT`, run the _1:1 Messages
  462. // Submit Steps_ with `messages` set from the following properties:
  463. // - `created-at` set to `reacted-at`,
  464. // - to construct a `Reaction` message from `reaction`.
  465. // 6. If the sender or the receiver does not have `REACTION_SUPPORT`, run the
  466. // _1:1 Messages Submit Steps_ with `messages` set from the following
  467. // properties:
  468. // - `created-at` set to `reacted-at`,
  469. // - to construct the `legacy-reaction`.
  470. // 7. Apply `reaction` (i.e. apply or withdraw) to the referred message with the
  471. // `reacted-at` timestamp.
  472. //
  473. // When the user submits a reaction in a group conversation:
  474. //
  475. // 1. Let `reaction` be the reaction to be applied to or withdrawn from a
  476. // referred message which must contain a single fully-qualified [emoji
  477. // codepoint sequence that is part of the currently supported Unicode
  478. // standard][emoji-test.txt].
  479. // 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let
  480. // `legacy-reaction` be the result.
  481. // 3. If `legacy-reaction` is not defined:
  482. // 1. If the sender does not have `REACTION_SUPPORT`, log a warning and abort
  483. // these steps.²
  484. // 2. If all of the group members do not have `REACTION_SUPPORT`, log a
  485. // warning and and abort these steps.²
  486. // 3. If any of the group members do not have `REACTION_SUPPORT`, notify the
  487. // user that the affected contacts will not receive the reaction.
  488. // 4. Let `reacted-at` be the current timestamp.
  489. // 5. Run the _Group Messages Submit Steps_ with `messages` set from the
  490. // following properties:
  491. // - `created-at` set to `reacted-at`,
  492. // - to construct a _canonical_ `Reaction` message from `reaction`,
  493. // - to construct a _specific_ message in the following way:
  494. // 1. Let `receiver` be the specific receiver.
  495. // 2. If the `receiver` does not have `REACTION_SUPPORT` and
  496. // `legacy-reaction` is defined, return the `legacy-reaction` (wrapped
  497. // by [`group-member-container`](ref:e2e.group-member-container)).
  498. // 3. Construct and return the _canonical_ `Reaction` message from
  499. // `reaction` (wrapped by
  500. // [`group-member-container`](ref:e2e.group-member-container)).³
  501. // 6. Apply `reaction` (i.e. apply or withdraw) to the referred message with the
  502. // `reacted-at` timestamp.
  503. //
  504. // The following steps are defined as the _Legacy Reaction Mapping Steps_:
  505. //
  506. // 1. If `action` is of variant `apply`:
  507. // 1. If `action.apply` equals one of the following codepoint sequences,
  508. // return a `e2e.delivery-receipt` of type _acknowledge_ (0x03):
  509. // - `1F44D` (👍)
  510. // - `1F44D 1F3FB` (👍🏻)
  511. // - `1F44D 1F3FC` (👍🏼)
  512. // - `1F44D 1F3FD` (👍🏽)
  513. // - `1F44D 1F3FE` (👍🏾)
  514. // - `1F44D 1F3FF` (👍🏿)
  515. // 2. If `action.apply` equals one of the following codepoint sequences,
  516. // return a `e2e.delivery-receipt` of type _decline_ (0x04):
  517. // - `1F44E` (👎)
  518. // - `1F44E 1F3FB` (👎🏻)
  519. // - `1F44E 1F3FC` (👎🏼)
  520. // - `1F44E 1F3FD` (👎🏽)
  521. // - `1F44E 1F3FE` (👎🏾)
  522. // - `1F44E 1F3FF` (👎🏿)
  523. // 2. Return no message.
  524. //
  525. // When reflected from another device as an incoming or outgoing 1:1 message:
  526. //
  527. // 1. Run the _Common Reaction Receive Steps_.
  528. //
  529. // When receiving this message:
  530. //
  531. // 1. Run the _Common Reaction Receive Steps_.
  532. //
  533. // When receiving this message (wrapped by
  534. // [`group-member-container`](ref:e2e.group-member-container)):
  535. //
  536. // 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the reaction
  537. // message has been discarded, abort these steps.
  538. // 1. Run the _Common Reaction Receive Steps_.
  539. //
  540. // The following steps are defined as the _Common Reaction Receive Steps_:
  541. //
  542. // 1. Lookup the referred message with `message_id` within the associated
  543. // conversation and let `referred-message` be the result.
  544. // 2. If `referred-message` is not defined, discard the message and abort these
  545. // steps.
  546. // 3. If `referred-message` is not reactable (see the associated _Reactions_
  547. // property), discard the message and abort these steps.
  548. // 4. If `action` is of variant `apply`:
  549. // 1. If `apply` contains more than 64 bytes, discard the message and abort
  550. // these steps.
  551. // 2. Decode `apply` to a UTF-8 string. If the string is empty, discard the
  552. // message and abort these steps.
  553. // 3. Apply (or re-apply) the resulting emoji from the sender to
  554. // `referred-message` with the message's (the `Reaction`'s) `created-at`
  555. // timestamp used for the time of reaction.⁴⁵
  556. // 5. If `action` is of variant `withdraw`:
  557. // 1. If `withdraw` contains more than 64 bytes, discard the message and
  558. // abort these steps.
  559. // 2. Decode `withdraw` to a UTF-8 string. If the string is empty, discard
  560. // the message and abort these steps.
  561. // 3. Remove the resulting emoji reaction from the sender for `message`.⁴⁵
  562. //
  563. // ¹: The UI should not allow to create non-legacy reactions in 1:1
  564. // conversations with a sender or receiver that does not have
  565. // `REACTION_SUPPORT`.
  566. //
  567. // ²: The UI should not allow to create non-legacy reactions in group
  568. // conversations with a sender that does not have `REACTION_SUPPORT` or when all
  569. // other group members don't have `REACTION_SUPPORT`.
  570. //
  571. // ³: In case the reaction could not be mapped to a legacy reaction, this
  572. // results in a `Reaction` message being sent to group members that currently do
  573. // not support reactions. This is intentional.
  574. //
  575. // ⁴: Note that the _apply_ mechanism is additive, meaning multiple reactions
  576. // from the same sender are allowed on a single message. This is why the
  577. // _withdraw_ mechanism is needed which removes a specific reaction. On the
  578. // other hand, a deprecated `e2e.delivery-receipt` will replace all existing
  579. // reactions of the sender at once (including these new-style reactions).
  580. //
  581. // ⁵: The UI should display a placeholder (�) for unknown emojis, meaining those
  582. // which are not a single fully-qualified [emoji codepoint sequence that is part
  583. // of the currently supported Unicode standard][emoji-test.txt]. But the
  584. // individual code sequences still have individual display buckets.
  585. //
  586. // [emoji-test.txt]: https://www.unicode.org/Public/emoji/latest/emoji-test.txt
  587. message Reaction {
  588. // Unique ID of the referred message.
  589. fixed64 message_id = 1;
  590. // A single emoji reaction to be applied or withdrawn.
  591. oneof action {
  592. // Apply a new emoji reaction.
  593. bytes apply = 2;
  594. // Withdraw a specific emoji reaction.
  595. bytes withdraw = 3;
  596. }
  597. }
  598. // Request joining a group.
  599. //
  600. // This message is sent to the administrator of a group. The required
  601. // information is provided by a `GroupInvite` URL payload.
  602. //
  603. // **Properties**:
  604. // - Kind: 1:1
  605. // - Flags:
  606. // - `0x01`: Send push notification.
  607. // - User profile distribution: Yes
  608. // - Exempt from blocking: Yes
  609. // - Implicit _direct_ contact creation: Yes
  610. // - Protect against replay: Yes
  611. // - Reflect:
  612. // - Incoming: Yes
  613. // - Outgoing: Yes
  614. // - _Sent_ update: No
  615. // - Delivery receipts: No
  616. // - Reactions: No
  617. // - When rejected: N/A (ignored)
  618. // - Edit applies to: N/A
  619. // - Deletable by: User only
  620. // - Send to Threema Gateway ID group creator: N/A
  621. //
  622. // When receiving this message:
  623. //
  624. // 1. Look up the corresponding group invitation by the token.
  625. // 2. If the group invitation could not be found, discard the message and abort
  626. // these steps.
  627. // 3. If the sender is already part of the group, send an accept response and
  628. // then respond as if the sender had sent a `group-sync-request` (i.e. send a
  629. // `group-setup`, `group-name`, etc.). Finally, abort these steps.
  630. // 4. If the group name does not match the name in the originally sent group
  631. // invitation, discard the message and abort these steps.
  632. // 5. If the group invitation has expired, send the respective response and
  633. // abort these steps.
  634. // 6. If the group invitation requires the admin to accept the request, show
  635. // this information in the user interface and pause these steps until the
  636. // user manually confirmed of rejected the request. Note that the date of the
  637. // decision is allowed to extend beyond the expiration date of the group
  638. // invitation. Continue with the following sub-steps once the user made a
  639. // decision on the request:
  640. // 1. If the user manually rejected the request, send the respective
  641. // response and abort these steps.
  642. // 7. If the group is full, send the respective response and abort these steps.
  643. // 8. Send an accept response.
  644. // 9. Add the sender of the group invitation request to the group and follow the
  645. // group protocol from there.
  646. message GroupJoinRequest {
  647. // The group invite token, 16 bytes
  648. bytes token = 1;
  649. // The group name from the group invite URL
  650. string group_name = 2;
  651. // A message for the group administrator, e.g. for identification purposes
  652. //
  653. // The message helps the administrator to decide whether or not to accept a
  654. // join request.
  655. //
  656. // Should be requested by the user interface for invitations that require
  657. // manual confirmation by the administrator. Should not be requested in case
  658. // the invitation will be automatically accepted.
  659. string message = 3;
  660. }
  661. // Response sent by the admin of a group towards a sender of a valid group join
  662. // request.
  663. //
  664. // **Properties**:
  665. // - Kind: 1:1
  666. // - Flags: None
  667. // - User profile distribution: Yes
  668. // - Exempt from blocking: Yes
  669. // - Implicit _direct_ contact creation: Yes
  670. // - Protect against replay: Yes
  671. // - Reflect:
  672. // - Incoming: Yes
  673. // - Outgoing: Yes
  674. // - _Sent_ update: No
  675. // - Delivery receipts: No
  676. // - Reactions: No
  677. // - When rejected: N/A (ignored)
  678. // - Edit applies to: N/A
  679. // - Deletable by: N/A
  680. // - Send to Threema Gateway ID group creator: N/A
  681. //
  682. // When receiving this message:
  683. //
  684. // 1. Look up the corresponding group join request by the token and the
  685. // sender's Threema ID as the administrator's Threema ID.
  686. // 2. If the group join request could not be found, discard the message and
  687. // abort these steps.
  688. // 3. Mark the group join request as accepted or (automatically) rejected by
  689. // the given response type.
  690. // 4. If the group join request has been accepted, remember the group id in
  691. // order to be able to map an incoming `group-setup` to the group.
  692. message GroupJoinResponse {
  693. // The group invite token, 16 bytes
  694. bytes token = 1;
  695. // Response of the admin
  696. message Response {
  697. // Accept a group invite request
  698. message Accept {
  699. // Group ID (little-endian) as chosen by the group creator
  700. //
  701. // Note: Combined with the Threema ID of the administrator, this forms the
  702. // `GroupIdentity`.
  703. fixed64 group_id = 1;
  704. }
  705. oneof response {
  706. // Accept a group invite request
  707. Accept accept = 1;
  708. // Token of a group invitation expired
  709. common.Unit expired = 2;
  710. // Group invitation cannot be accepted due to the group being full
  711. common.Unit group_full = 3;
  712. // The administrator explicitly rejects the invitation request
  713. common.Unit reject = 4;
  714. }
  715. }
  716. Response response = 2;
  717. }